lepidoptera 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +2 -0
- data/HISTORY.md +22 -0
- data/README.md +151 -0
- data/Rakefile +26 -0
- data/bin/lep +117 -0
- data/heroku_generators/sinatra/INFO +10 -0
- data/heroku_generators/sinatra/sinatra_generator.rb +18 -0
- data/heroku_generators/sinatra/templates/.gems +1 -0
- data/heroku_generators/sinatra/templates/README.md +5 -0
- data/heroku_generators/sinatra/templates/app.rb +23 -0
- data/heroku_generators/sinatra/templates/config.ru +3 -0
- data/heroku_generators/static/INFO +10 -0
- data/heroku_generators/static/static_generator.rb +24 -0
- data/heroku_generators/static/templates/README.md +27 -0
- data/heroku_generators/static/templates/config.ru +28 -0
- data/heroku_generators/static/templates/public/css/main.css +0 -0
- data/heroku_generators/static/templates/public/index.html +23 -0
- data/heroku_generators/static/templates/public/js/app.js +0 -0
- data/jquery_generators/plugin/INFO +0 -0
- data/jquery_generators/plugin/plugin_generator.rb +16 -0
- data/jquery_generators/plugin/templates/demo.html +29 -0
- data/jquery_generators/plugin/templates/js/jquery.plugin_name.js +57 -0
- data/lepidoptera.gemspec +73 -0
- data/lib/base.rb +48 -0
- data/lib/butterfly.rb +122 -0
- data/lib/options.rb +112 -0
- metadata +133 -0
data/.gitignore
ADDED
data/HISTORY.md
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
## Version 0.2.0, released 07.11.2010
|
2
|
+
|
3
|
+
Due to a naming conflict with [an other project][1], I changed the name of the project and of the gem from __butterfly__ to __lepidoptera__, which is etymological the same.
|
4
|
+
|
5
|
+
* [CHG] renaming of executable.
|
6
|
+
|
7
|
+
|
8
|
+
## Version 0.1.1, released 06.11.2010
|
9
|
+
|
10
|
+
kolleske made some fixes for Windows compatibility.
|
11
|
+
|
12
|
+
* [FIX] require win32console to use cli color on Windows.
|
13
|
+
* [FIX] set explicitly an executable file.
|
14
|
+
|
15
|
+
|
16
|
+
## Version 0.1.0, released 04.11.2010
|
17
|
+
|
18
|
+
Initial release!
|
19
|
+
|
20
|
+
|
21
|
+
|
22
|
+
[1]: http://butterflycode.sourceforge.net/ "Butterfly Code Generator"
|
data/README.md
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
lepidoptera
|
2
|
+
===========
|
3
|
+
|
4
|
+
Lepidoptera /ˌlɛpɪˈdɒptərə/
|
5
|
+
|
6
|
+
1. _an order of insects that comprises the butterflies and moths. They have four large scale-covered wings that bear distinctive markings, and larvae that are caterpillars._ ORIGIN _modern Latin (plural), from Greek lepis, lepid- ‘scale’ + pteron ‘wing.’_
|
7
|
+
|
8
|
+
2. _A life-enhancing __code generator__ for everyday use._
|
9
|
+
|
10
|
+
What is lepidoptera?
|
11
|
+
--------------------
|
12
|
+
|
13
|
+
Lepidoptera is a very simple and easy extensible __code generator for common every day projects__.
|
14
|
+
Technically, Lepidoptera is a wrapper for [rubigen][r] which allows setting up code templates for arbitrary projects.
|
15
|
+
|
16
|
+
Code generators integrated into Lepidoptera are structured in __generator groups__, whereas every group can have multiple __generator types__.
|
17
|
+
|
18
|
+
For the time being, Lepidoptera has code generators for the following projects (more to come):
|
19
|
+
|
20
|
+
* [jquery][j] plugins,
|
21
|
+
* static pages hosted on [heroku][h],
|
22
|
+
* [sinatra][s] application hosted on [heroku][h].
|
23
|
+
|
24
|
+
Installation
|
25
|
+
------------
|
26
|
+
|
27
|
+
$ sudo gem install lepidoptera
|
28
|
+
|
29
|
+
As [lep][wiki-2] (/ˈlɛp/) is a short for [lepidoptera][wiki-1], this gem will install an executable `lep`
|
30
|
+
|
31
|
+
For aesthetic reasons, you may also set a synonym executable `butterfly` alias in your `.bashrc` file:
|
32
|
+
|
33
|
+
$ alias butterfly='lep $1'
|
34
|
+
|
35
|
+
Usage
|
36
|
+
-----
|
37
|
+
|
38
|
+
for grouped code generators:
|
39
|
+
|
40
|
+
lep [options] <generator-group> <generator-type> <project-name>
|
41
|
+
|
42
|
+
or for ungrouped code generators:
|
43
|
+
|
44
|
+
lep [options] <generator-type> <project-name>
|
45
|
+
|
46
|
+
with the following __options__:
|
47
|
+
|
48
|
+
-q, --quiet Suppress status output.
|
49
|
+
-g, --git Create a git repository after code generation.
|
50
|
+
-n, --new Add a new code generator in ~/.lepidoptera
|
51
|
+
-h, --help Print generator's options and usage.
|
52
|
+
|
53
|
+
and - for the time being - the following __code generators__ which are included in this gem:
|
54
|
+
|
55
|
+
heroku static
|
56
|
+
heroku sinatra
|
57
|
+
jquery plugin
|
58
|
+
|
59
|
+
Helpers
|
60
|
+
-------
|
61
|
+
|
62
|
+
Get a list of all code generators grouped by generator-groups:
|
63
|
+
|
64
|
+
$ lep
|
65
|
+
|
66
|
+
Get a list of all code generator-types for a given generator-group:
|
67
|
+
|
68
|
+
$ lep <generator-group>
|
69
|
+
|
70
|
+
Extending Code Generators
|
71
|
+
-------------------------
|
72
|
+
|
73
|
+
Since lepidoptera is based on _Nic Williams_ Ruby generator framework [rubigen][r], it is very simple to add new own private code generators.
|
74
|
+
|
75
|
+
You may include new code generators by putting the following code structure into `~/.lepidoptera`:
|
76
|
+
|
77
|
+
~/.lepidoptera
|
78
|
+
└─ name
|
79
|
+
├─ INFO
|
80
|
+
├─ name_generator.rb
|
81
|
+
└─ template
|
82
|
+
├─ a file
|
83
|
+
├─ ...
|
84
|
+
└─ a folder
|
85
|
+
|
86
|
+
Much more easy is to use a generator generator which generates the above code generator stub into `~/.lepidoptera`: (TODO)
|
87
|
+
|
88
|
+
$ lep -n <type-of-code-generator>
|
89
|
+
$ lep -n <code-generator-group> <type-of-code-generator>
|
90
|
+
|
91
|
+
Integrated Code Generators
|
92
|
+
==========================
|
93
|
+
|
94
|
+
jQuery Generators
|
95
|
+
-----------------
|
96
|
+
|
97
|
+
get List of all jquery generators:
|
98
|
+
|
99
|
+
$ lep jquery
|
100
|
+
|
101
|
+
generate code for a jquery plugin:
|
102
|
+
|
103
|
+
$ lep jquery plugin <plugin-name>
|
104
|
+
|
105
|
+
Heroku Generators
|
106
|
+
-----------------
|
107
|
+
|
108
|
+
get List of all heroku generators:
|
109
|
+
|
110
|
+
$ lep heroku
|
111
|
+
|
112
|
+
generate code for a static page on heroku:
|
113
|
+
|
114
|
+
$ lep heroku static <page-name>
|
115
|
+
|
116
|
+
generate code for a sinatra application on heroku:
|
117
|
+
|
118
|
+
$ lep heroku sinatra <app-name>
|
119
|
+
|
120
|
+
License
|
121
|
+
=======
|
122
|
+
|
123
|
+
Copyright 2010 Thomas Duerr (me@thomd.net)
|
124
|
+
|
125
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
126
|
+
a copy of this software and associated documentation files (the
|
127
|
+
'Software'), to deal in the Software without restriction, including
|
128
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
129
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
130
|
+
permit persons to whom the Software is furnished to do so, subject to
|
131
|
+
the following conditions:
|
132
|
+
|
133
|
+
The above copyright notice and this permission notice shall be
|
134
|
+
included in all copies or substantial portions of the Software.
|
135
|
+
|
136
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
137
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
138
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
139
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
140
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
141
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
142
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
143
|
+
|
144
|
+
|
145
|
+
[wiki-1]: http://en.wikipedia.org/wiki/Lepidoptera "Lepidoptera on Wiktionary"
|
146
|
+
[wiki-2]: http://en.wiktionary.org/wiki/lep "Lep on Wiktionary"
|
147
|
+
[j]: http://jquery.com/ "jQuery: The Write Less, Do More, JavaScript Library"
|
148
|
+
[h]: http://heroku.com/ "heroku | Ruby Cloud Platform as a Service"
|
149
|
+
[s]: http://www.sinatrarb.com/ "Sinatra"
|
150
|
+
[r]: http://rubigen.rubyforge.org/ "rubigen - Ruby Generator Framework"
|
151
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#
|
2
|
+
# generate gemspec file
|
3
|
+
#
|
4
|
+
# usage:
|
5
|
+
# rake -T
|
6
|
+
#
|
7
|
+
begin
|
8
|
+
require 'jeweler'
|
9
|
+
require File.dirname(__FILE__) + '/lib/butterfly'
|
10
|
+
Jeweler::Tasks.new do |gemspec|
|
11
|
+
gemspec.name = "lepidoptera"
|
12
|
+
gemspec.version = Butterfly::VERSION
|
13
|
+
gemspec.summary = "a life-enhancing code generator for everyday use"
|
14
|
+
gemspec.description = "Lepidoptera is a very simple and easy extensible code generator for common every day projects."
|
15
|
+
gemspec.email = "thomduerr@gmail.com"
|
16
|
+
gemspec.homepage = "http://github.com/thomd/lepidoptera/"
|
17
|
+
gemspec.authors = ["Thomas Duerr"]
|
18
|
+
gemspec.executables = ["lep"]
|
19
|
+
gemspec.add_dependency "rubigen", ">= 1.5.5"
|
20
|
+
gemspec.add_dependency "git", ">= 1.2.5"
|
21
|
+
gemspec.add_development_dependency "jeweler", ">= 1.4.0"
|
22
|
+
end
|
23
|
+
Jeweler::GemcutterTasks.new
|
24
|
+
rescue LoadError
|
25
|
+
puts "Jeweler not available. Install it with: gem install jeweler"
|
26
|
+
end
|
data/bin/lep
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'optparse'
|
5
|
+
require 'rubigen'
|
6
|
+
require 'rubigen/scripts/generate'
|
7
|
+
require File.dirname(__FILE__) + "/../lib/butterfly"
|
8
|
+
require File.dirname(__FILE__) + "/../lib/options"
|
9
|
+
require File.dirname(__FILE__) + "/../lib/base"
|
10
|
+
|
11
|
+
|
12
|
+
# defines some colors for a nice command-line output
|
13
|
+
begin
|
14
|
+
require 'Win32/Console/ANSI' if RUBY_PLATFORM =~ /win32/
|
15
|
+
rescue LoadError
|
16
|
+
raise 'You must gem install win32console to use color on Windows'
|
17
|
+
end
|
18
|
+
PURPLE = "\033[0;35m"
|
19
|
+
BLUE = "\033[0;34m"
|
20
|
+
WHITE = "\033[0;37m"
|
21
|
+
GREEN = "\033[0;32m"
|
22
|
+
YELLOW = "\033[0;33m"
|
23
|
+
RED = "\033[0;31m"
|
24
|
+
|
25
|
+
|
26
|
+
### Set up generators
|
27
|
+
|
28
|
+
# get code generators
|
29
|
+
generators = Butterfly::CodeGenerators.new
|
30
|
+
|
31
|
+
|
32
|
+
### Parse options and arguments from command-line
|
33
|
+
|
34
|
+
# get options parser
|
35
|
+
parser = Butterfly::Options::Parser.new(generators)
|
36
|
+
|
37
|
+
# parse and get options
|
38
|
+
options = parser.parse(ARGV)
|
39
|
+
|
40
|
+
|
41
|
+
# After parsing the options,
|
42
|
+
# * first argument should be <generator-group>
|
43
|
+
# * second argument should be <generator-type>
|
44
|
+
# * third argument should be a <project_name>
|
45
|
+
#
|
46
|
+
# If no argument is left, show a list of available generator-groups
|
47
|
+
if ARGV.empty?
|
48
|
+
parser.show_groups
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# If one argument is provided, regard it as the name of a generator-group.
|
53
|
+
# If the generator-group name is an existing generator-group, show a list of available generator-types
|
54
|
+
if ARGV.length == 1
|
55
|
+
|
56
|
+
generator_group = ARGV[0]
|
57
|
+
|
58
|
+
if generators.names.include?(generator_group)
|
59
|
+
parser.show_types(generator_group)
|
60
|
+
else
|
61
|
+
raise Butterfly::GeneratorError, "#{RED}generator group '#{generator_group}' does not exist.#{WHITE}"
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
|
67
|
+
# If two arguments are provided, regard the first as the name of a generator-group and the second as the name of a generator-type.
|
68
|
+
# If the generator-type name is an existing generator-type, ask for a project name
|
69
|
+
if ARGV.length == 2
|
70
|
+
|
71
|
+
generator_group = ARGV[0]
|
72
|
+
generator_types = generators.types_of(generator_group)
|
73
|
+
generator_type = ARGV[1]
|
74
|
+
|
75
|
+
if generator_types.include?(generator_type)
|
76
|
+
parser.ask_for_project(generator_group, generator_type)
|
77
|
+
else
|
78
|
+
raise Butterfly::GeneratorError, "#{RED}generator type '#{generator_type}' does not exist in generator group '#{generator_group}'.#{WHITE}"
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# If three arguments are provided, the first is the generator-group, the second the generator-type ans the thirs the project name.
|
85
|
+
generator_group = ARGV.shift
|
86
|
+
generator_type = ARGV.shift
|
87
|
+
|
88
|
+
# check if generator group exists
|
89
|
+
if !generators.names.include?(generator_group)
|
90
|
+
raise Butterfly::GeneratorError, "#{RED}generator group '#{generator_group}' does not exist.#{WHITE}"
|
91
|
+
end
|
92
|
+
|
93
|
+
# check if generator type exists
|
94
|
+
if !generators.types_of(generator_group).include?(generator_type)
|
95
|
+
raise Butterfly::GeneratorError, "#{RED}generator type '#{generator_type}' does not exist in generator group '#{generator_group}'.#{WHITE}"
|
96
|
+
end
|
97
|
+
|
98
|
+
project_name = ARGV[0]
|
99
|
+
|
100
|
+
|
101
|
+
# DEBUG
|
102
|
+
#puts "generator group: #{generator_group}"
|
103
|
+
#puts "generator type: #{generator_type}"
|
104
|
+
#puts "project name: #{project_name}"
|
105
|
+
#puts "options: #{options}"
|
106
|
+
|
107
|
+
|
108
|
+
### generate code!
|
109
|
+
|
110
|
+
# Add only the code generator of the selected generator-group to the beginning of a list of sources.
|
111
|
+
# This is to make generator-types with the same name clear
|
112
|
+
RubiGen::Base.prepend_sources(generators.source_of(generator_group))
|
113
|
+
|
114
|
+
|
115
|
+
# generate a new project <project_name> of type <generator_type>
|
116
|
+
RubiGen::Scripts::Generate.new.run(ARGV, :generator => generator_type, :quiet => options[:quiet], :gitinit => options[:gitinit])
|
117
|
+
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class SinatraGenerator < Butterfly::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
|
6
|
+
# Ensure appropriate generators folder exists
|
7
|
+
m.directory ""
|
8
|
+
|
9
|
+
# Generator stub
|
10
|
+
m.template "app.rb", "#{@name}_app.rb"
|
11
|
+
m.template "config.ru", "config.ru"
|
12
|
+
m.template "README.md", "README.md"
|
13
|
+
m.file ".gems", ".gems"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1 @@
|
|
1
|
+
sinatra
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'sinatra'
|
3
|
+
|
4
|
+
configure :production do
|
5
|
+
# Configure stuff here you'll want to
|
6
|
+
# only be run at Heroku at boot
|
7
|
+
|
8
|
+
# TIP: You can get you database information
|
9
|
+
# from ENV['DATABASE_URI'] (see /env route below)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Quick test
|
13
|
+
get '/' do
|
14
|
+
"<%= name %> on Heroku!"
|
15
|
+
end
|
16
|
+
|
17
|
+
# You can see all your app specific information this way.
|
18
|
+
# IMPORTANT! This is a very bad thing to do for a production
|
19
|
+
# application with sensitive information
|
20
|
+
|
21
|
+
# get '/env' do
|
22
|
+
# ENV.inspect
|
23
|
+
# end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class StaticGenerator < Butterfly::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
|
6
|
+
# installation skeleton (intermediate directories are automatically created).
|
7
|
+
%w(
|
8
|
+
public/css
|
9
|
+
public/js
|
10
|
+
public/images
|
11
|
+
).each { |path| m.directory path }
|
12
|
+
|
13
|
+
# Create file stubs
|
14
|
+
%w(
|
15
|
+
config.ru
|
16
|
+
README.md
|
17
|
+
public/index.html
|
18
|
+
public/css/main.css
|
19
|
+
public/js/app.js
|
20
|
+
).each { |file| m.template file, file }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<%= name %>
|
2
|
+
===========
|
3
|
+
|
4
|
+
A static page for deployment on [heroku][1]:
|
5
|
+
|
6
|
+
Author: <%= author %>
|
7
|
+
|
8
|
+
Deployment
|
9
|
+
----------
|
10
|
+
|
11
|
+
<% if !gitinit then %>
|
12
|
+
$ git init
|
13
|
+
<%- end -%>
|
14
|
+
$ ...
|
15
|
+
$ heroku create <%= name %>
|
16
|
+
$ git push heroku master
|
17
|
+
$ heroku open
|
18
|
+
|
19
|
+
Meta
|
20
|
+
----
|
21
|
+
|
22
|
+
the `index.html` loads a [CSS Reset][2] and the [jQuery 1.4.3][3] library.
|
23
|
+
|
24
|
+
|
25
|
+
[1]: http://heroku.com/ "Heroku"
|
26
|
+
[2]: http://code.google.com/p/reset5/ "HTML5 CSS Reset"
|
27
|
+
[3]: http://jquery.com/ "jquery.com"
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#
|
2
|
+
# deploy a static page on heroku
|
3
|
+
# ------------------------------
|
4
|
+
#
|
5
|
+
#
|
6
|
+
# required site structure:
|
7
|
+
#
|
8
|
+
# name-of-site
|
9
|
+
# |- config.ru
|
10
|
+
# +- public
|
11
|
+
# |- index.html
|
12
|
+
# |- css
|
13
|
+
# |- js
|
14
|
+
# +- images
|
15
|
+
#
|
16
|
+
#
|
17
|
+
#
|
18
|
+
# deployment:
|
19
|
+
#
|
20
|
+
# git init
|
21
|
+
# ...
|
22
|
+
# heroku create <name-of-site>
|
23
|
+
# git push heroku master
|
24
|
+
#
|
25
|
+
#
|
26
|
+
|
27
|
+
use Rack::Static, :urls => ["/css", "/images", "/js"], :root => "public"
|
28
|
+
run lambda { |env| [200, { 'Content-Type' => 'text/html', 'Cache-Control' => 'public, max-age=86400' }, File.open('public/index.html', File::RDONLY)] }
|
File without changes
|
@@ -0,0 +1,23 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
6
|
+
|
7
|
+
<title><%= name %></title>
|
8
|
+
|
9
|
+
<link rel="stylesheet" href="http://reset5.googlecode.com/hg/reset.css" />
|
10
|
+
<link rel="stylesheet" href="css/main.css" />
|
11
|
+
</head>
|
12
|
+
<body>
|
13
|
+
|
14
|
+
<h1><%= name %></h1>
|
15
|
+
|
16
|
+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
|
17
|
+
<script type="text/javascript" src="js/app.js"></script>
|
18
|
+
<script type="text/javascript">
|
19
|
+
$(function(){
|
20
|
+
|
21
|
+
});
|
22
|
+
</script>
|
23
|
+
</body>
|
File without changes
|
File without changes
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class PluginGenerator < Butterfly::Base
|
2
|
+
|
3
|
+
def manifest
|
4
|
+
record do |m|
|
5
|
+
|
6
|
+
# Ensure appropriate generators folder exists
|
7
|
+
m.directory "js"
|
8
|
+
|
9
|
+
# Generator stub
|
10
|
+
m.template "js/jquery.plugin_name.js", "js/jquery.#{@name}.js"
|
11
|
+
m.template "demo.html", "demo.html"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
6
|
+
|
7
|
+
<title>jquery.<%= name %>.js</title>
|
8
|
+
|
9
|
+
<link rel="stylesheet" href="http://reset5.googlecode.com/hg/reset.css" />
|
10
|
+
</head>
|
11
|
+
<body>
|
12
|
+
|
13
|
+
<h1>jquery.<%= name %>.js</h1>
|
14
|
+
|
15
|
+
<ul>
|
16
|
+
<li>element-1</li>
|
17
|
+
<li>element-2</li>
|
18
|
+
<li>element-3</li>
|
19
|
+
<li>element-4</li>
|
20
|
+
</ul>
|
21
|
+
|
22
|
+
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.3/jquery.min.js"></script>
|
23
|
+
<script type="text/javascript" src="js/jquery.<%= name %>.js"></script>
|
24
|
+
<script type="text/javascript">
|
25
|
+
$(function(){
|
26
|
+
$('li').<%= name %>();
|
27
|
+
});
|
28
|
+
</script>
|
29
|
+
</body>
|
@@ -0,0 +1,57 @@
|
|
1
|
+
/*
|
2
|
+
* jquery <%= name %> plugin
|
3
|
+
*
|
4
|
+
* author: <%= author %>
|
5
|
+
*
|
6
|
+
*/
|
7
|
+
(function($) {
|
8
|
+
|
9
|
+
//
|
10
|
+
// plugin definition
|
11
|
+
//
|
12
|
+
$.fn.<%= name %> = function(options) {
|
13
|
+
|
14
|
+
debug(this);
|
15
|
+
|
16
|
+
// merge options into default options
|
17
|
+
var opts = $.extend({}, $.fn.<%= name %>.defaults, options);
|
18
|
+
|
19
|
+
// iterate through each matched element
|
20
|
+
return this.each(function() {
|
21
|
+
|
22
|
+
$this = $(this);
|
23
|
+
|
24
|
+
// build element specific options
|
25
|
+
var o = $.meta ? $.extend({}, opts, $this.data()) : opts;
|
26
|
+
|
27
|
+
// TODO
|
28
|
+
|
29
|
+
|
30
|
+
});
|
31
|
+
};
|
32
|
+
|
33
|
+
|
34
|
+
//
|
35
|
+
// private debug function
|
36
|
+
//
|
37
|
+
function debug(obj) {
|
38
|
+
if (window.console && window.console.log)
|
39
|
+
window.console.log('<%= name %> selection count: ' + obj.size());
|
40
|
+
};
|
41
|
+
|
42
|
+
//
|
43
|
+
// define function to be called from outside
|
44
|
+
//
|
45
|
+
$.fn.<%= name %>.foo = function() {
|
46
|
+
|
47
|
+
};
|
48
|
+
|
49
|
+
//
|
50
|
+
// plugin defaults
|
51
|
+
//
|
52
|
+
$.fn.<%= name %>.defaults = {
|
53
|
+
property1: 'value1',
|
54
|
+
property2: 'value2'
|
55
|
+
};
|
56
|
+
|
57
|
+
})(jQuery);
|
data/lepidoptera.gemspec
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{lepidoptera}
|
8
|
+
s.version = "0.2.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Thomas Duerr"]
|
12
|
+
s.date = %q{2010-11-07}
|
13
|
+
s.default_executable = %q{lep}
|
14
|
+
s.description = %q{Lepidoptera is a very simple and easy extensible code generator for common every day projects.}
|
15
|
+
s.email = %q{thomduerr@gmail.com}
|
16
|
+
s.executables = ["lep"]
|
17
|
+
s.extra_rdoc_files = [
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gitignore",
|
22
|
+
"HISTORY.md",
|
23
|
+
"README.md",
|
24
|
+
"Rakefile",
|
25
|
+
"bin/lep",
|
26
|
+
"heroku_generators/sinatra/INFO",
|
27
|
+
"heroku_generators/sinatra/sinatra_generator.rb",
|
28
|
+
"heroku_generators/sinatra/templates/.gems",
|
29
|
+
"heroku_generators/sinatra/templates/README.md",
|
30
|
+
"heroku_generators/sinatra/templates/app.rb",
|
31
|
+
"heroku_generators/sinatra/templates/config.ru",
|
32
|
+
"heroku_generators/static/INFO",
|
33
|
+
"heroku_generators/static/static_generator.rb",
|
34
|
+
"heroku_generators/static/templates/README.md",
|
35
|
+
"heroku_generators/static/templates/config.ru",
|
36
|
+
"heroku_generators/static/templates/public/css/main.css",
|
37
|
+
"heroku_generators/static/templates/public/index.html",
|
38
|
+
"heroku_generators/static/templates/public/js/app.js",
|
39
|
+
"jquery_generators/plugin/INFO",
|
40
|
+
"jquery_generators/plugin/plugin_generator.rb",
|
41
|
+
"jquery_generators/plugin/templates/demo.html",
|
42
|
+
"jquery_generators/plugin/templates/js/jquery.plugin_name.js",
|
43
|
+
"lepidoptera.gemspec",
|
44
|
+
"lib/base.rb",
|
45
|
+
"lib/butterfly.rb",
|
46
|
+
"lib/options.rb"
|
47
|
+
]
|
48
|
+
s.homepage = %q{http://github.com/thomd/lepidoptera/}
|
49
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
50
|
+
s.require_paths = ["lib"]
|
51
|
+
s.rubygems_version = %q{1.3.7}
|
52
|
+
s.summary = %q{a life-enhancing code generator for everyday use}
|
53
|
+
|
54
|
+
if s.respond_to? :specification_version then
|
55
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
56
|
+
s.specification_version = 3
|
57
|
+
|
58
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
59
|
+
s.add_runtime_dependency(%q<rubigen>, [">= 1.5.5"])
|
60
|
+
s.add_runtime_dependency(%q<git>, [">= 1.2.5"])
|
61
|
+
s.add_development_dependency(%q<jeweler>, [">= 1.4.0"])
|
62
|
+
else
|
63
|
+
s.add_dependency(%q<rubigen>, [">= 1.5.5"])
|
64
|
+
s.add_dependency(%q<git>, [">= 1.2.5"])
|
65
|
+
s.add_dependency(%q<jeweler>, [">= 1.4.0"])
|
66
|
+
end
|
67
|
+
else
|
68
|
+
s.add_dependency(%q<rubigen>, [">= 1.5.5"])
|
69
|
+
s.add_dependency(%q<git>, [">= 1.2.5"])
|
70
|
+
s.add_dependency(%q<jeweler>, [">= 1.4.0"])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
data/lib/base.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
|
2
|
+
module Butterfly
|
3
|
+
|
4
|
+
# extend Base class wwith base functionality for all butterfly generators
|
5
|
+
class Base < RubiGen::Base
|
6
|
+
|
7
|
+
attr_reader :name, :author, :gitinit
|
8
|
+
|
9
|
+
def initialize(runtime_args, runtime_options = {})
|
10
|
+
super
|
11
|
+
@destination_root = File.expand_path(args.shift)
|
12
|
+
@name = base_name
|
13
|
+
@author = ENV['USER']
|
14
|
+
@gitinit = runtime_options[:gitinit]
|
15
|
+
end
|
16
|
+
|
17
|
+
# do some final things after generation
|
18
|
+
def after_generate
|
19
|
+
git_init if @gitinit
|
20
|
+
info_message
|
21
|
+
end
|
22
|
+
|
23
|
+
protected
|
24
|
+
|
25
|
+
# create an empty git repository and commit generated files
|
26
|
+
def git_init
|
27
|
+
require 'git'
|
28
|
+
begin
|
29
|
+
g = Git.open(@destination_root)
|
30
|
+
logger.exists '.git'
|
31
|
+
rescue ArgumentError
|
32
|
+
g = Git.init(@destination_root)
|
33
|
+
g.add(@destination_root)
|
34
|
+
g.commit("beginning of #{@name} project")
|
35
|
+
logger.create '.git'
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# Read INFO from file in generator base path.
|
40
|
+
def info_message
|
41
|
+
info = File.read(File.join(spec.path, 'INFO')) rescue ''
|
42
|
+
template = ERB.new(info, nil, '<>')
|
43
|
+
puts "\n#{template.result(binding)}"
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
data/lib/butterfly.rb
ADDED
@@ -0,0 +1,122 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubigen'
|
5
|
+
|
6
|
+
|
7
|
+
module Butterfly
|
8
|
+
|
9
|
+
# Current version
|
10
|
+
VERSION = '0.2.0'
|
11
|
+
|
12
|
+
# path of build-in code generators
|
13
|
+
GENERATORS_PATH = File.join(File.dirname(__FILE__), '..', '*_generators')
|
14
|
+
|
15
|
+
# path of user code generators
|
16
|
+
USER_PATH = File.join(Dir.user_home, '.lepidoptera', '*_generators')
|
17
|
+
|
18
|
+
|
19
|
+
# Error handling
|
20
|
+
class GeneratorError < StandardError
|
21
|
+
end
|
22
|
+
|
23
|
+
class GeneratorSourceMissingError < StandardError
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
# Generator
|
28
|
+
class CodeGenerators
|
29
|
+
|
30
|
+
attr_accessor :generators
|
31
|
+
|
32
|
+
def initialize
|
33
|
+
@generators = []
|
34
|
+
|
35
|
+
# loop through build in code generators and user code generators
|
36
|
+
[GENERATORS_PATH, USER_PATH].each do |path|
|
37
|
+
Dir[path].each do |file|
|
38
|
+
@generators.push(GeneratorGroup.new(file)) if File.directory?(file)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# returns array of generator-group names
|
44
|
+
def names
|
45
|
+
generators.map{ |generator| generator.name }
|
46
|
+
end
|
47
|
+
|
48
|
+
# returns array of generator-group sources
|
49
|
+
def sources
|
50
|
+
generators.map{ |generator| generator.source }
|
51
|
+
end
|
52
|
+
|
53
|
+
# returns generator source for a given generator-group
|
54
|
+
def source_of(name)
|
55
|
+
selected = generators.select { |n| n.name == name }
|
56
|
+
if selected.length == 0
|
57
|
+
raise Butterfly::GeneratorSourceMissingError
|
58
|
+
else
|
59
|
+
selected[0].source
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# returns array of generator-types for a given generator-group
|
64
|
+
def types_of(name)
|
65
|
+
selected = generators.select { |n| n.name == name }
|
66
|
+
if selected.length == 0
|
67
|
+
[]
|
68
|
+
else
|
69
|
+
selected[0].types
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
# a generator-group contains a generator name, its path and its generator-types
|
75
|
+
class GeneratorGroup
|
76
|
+
|
77
|
+
attr_accessor :name, :source, :types, :label
|
78
|
+
|
79
|
+
def initialize(file)
|
80
|
+
@name = File.basename(file).gsub(/_generators$/, '')
|
81
|
+
@source = RubiGen::PathSource.new(:app, file)
|
82
|
+
@types = @source.names(:visible)
|
83
|
+
@label = @source.label
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
|
91
|
+
# tweaking some things in Rubigen which does not fit to Butterfly
|
92
|
+
module RubiGen
|
93
|
+
|
94
|
+
# adding colored output for logger
|
95
|
+
class SimpleLogger
|
96
|
+
def log(status, message, &block)
|
97
|
+
|
98
|
+
# define some status colors
|
99
|
+
status_color = {
|
100
|
+
:exists => RED,
|
101
|
+
:identical => BLUE,
|
102
|
+
:create => GREEN,
|
103
|
+
:force => GREEN,
|
104
|
+
:skip => RED
|
105
|
+
}
|
106
|
+
|
107
|
+
template = "#{status_color[status.to_sym]}%12s#{WHITE} %s%s\n"
|
108
|
+
template = "%12s %s%s\n" if RUBY_PLATFORM =~ /win32/
|
109
|
+
|
110
|
+
@out.print(template % [status, ' ' * @level, message]) unless quiet
|
111
|
+
indent(&block) if block_given?
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
# show not only generators with an USAGE file
|
116
|
+
# (don't understand the usecase for this in rubigen)
|
117
|
+
class Spec
|
118
|
+
def visible?
|
119
|
+
true
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
data/lib/options.rb
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
$:.unshift(File.dirname(__FILE__)) unless $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'rubigen'
|
5
|
+
require 'optparse'
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
# define global default option definitions
|
10
|
+
class OptionParser
|
11
|
+
def add_default(opts)
|
12
|
+
self.separator ""
|
13
|
+
|
14
|
+
# self.on("-n", "--new", "Add a new code generator in ~/.lepidoptera") do
|
15
|
+
# opts[:new] = true
|
16
|
+
# end
|
17
|
+
|
18
|
+
self.on("-q", "--quiet", "Suppress status output") do
|
19
|
+
opts[:quiet] = true
|
20
|
+
end
|
21
|
+
|
22
|
+
self.on("-g", "--git","Create a git repository after code generation") do
|
23
|
+
opts[:gitinit] = true
|
24
|
+
end
|
25
|
+
|
26
|
+
# self.on("-s", "--svn [URL]","Initial import into a given svn repository") do |url|
|
27
|
+
# opts[:svnimport] = url
|
28
|
+
# end
|
29
|
+
|
30
|
+
self.on("-h", "--help", "Show help") do
|
31
|
+
puts self
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
self.separator ""
|
36
|
+
self.define_head "Version #{Butterfly::VERSION}"
|
37
|
+
self.define_head "A life-enhancing code generator for everyday use."
|
38
|
+
self.define_head ""
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
module Butterfly
|
45
|
+
module Options
|
46
|
+
|
47
|
+
# Default options. Overriden by command-line options.
|
48
|
+
OPTIONS = {
|
49
|
+
:quiet => false,
|
50
|
+
:gitinit => false,
|
51
|
+
:svnimport => false,
|
52
|
+
:new => false
|
53
|
+
}
|
54
|
+
|
55
|
+
# parser class
|
56
|
+
class Parser
|
57
|
+
attr_accessor :generators
|
58
|
+
|
59
|
+
def initialize(generators)
|
60
|
+
@generators = generators
|
61
|
+
end
|
62
|
+
|
63
|
+
def parse(args)
|
64
|
+
options = OPTIONS
|
65
|
+
parser = OptionParser.new do |opts|
|
66
|
+
opts.add_default(options)
|
67
|
+
end
|
68
|
+
parser.parse!(args)
|
69
|
+
options
|
70
|
+
end
|
71
|
+
|
72
|
+
def show_groups
|
73
|
+
parser = OptionParser.new do |opts|
|
74
|
+
opts.banner = "Usage: #{PURPLE}#{File.basename($0)}#{WHITE} [options] #{BLUE}<generator-group>#{WHITE} <generator-type> <project-name>"
|
75
|
+
opts.add_default(options = {})
|
76
|
+
opts.separator "#{BLUE}Please choose a generator-group:#{WHITE}"
|
77
|
+
opts.separator ""
|
78
|
+
@generators.names.each do |name|
|
79
|
+
opts.separator " #{BLUE}#{name}#{WHITE}"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
parser.parse(["-h"])
|
83
|
+
exit
|
84
|
+
end
|
85
|
+
|
86
|
+
def show_types(generator_group)
|
87
|
+
parser = OptionParser.new do |opts|
|
88
|
+
opts.banner = "Usage: #{PURPLE}#{File.basename($0)}#{WHITE} [options] #{PURPLE}#{generator_group}#{WHITE} #{BLUE}<generator-type>#{WHITE} <project-name>"
|
89
|
+
opts.add_default(options = {})
|
90
|
+
opts.separator "#{BLUE}Please choose a #{generator_group} generator-type:#{WHITE}"
|
91
|
+
opts.separator ""
|
92
|
+
@generators.types_of(generator_group).each do |type|
|
93
|
+
opts.separator " #{BLUE}#{type}#{WHITE}"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
parser.parse(["-h"])
|
97
|
+
exit
|
98
|
+
end
|
99
|
+
|
100
|
+
def ask_for_project(generator_group, generator_type)
|
101
|
+
parser = OptionParser.new do |opts|
|
102
|
+
opts.banner = "Usage: #{PURPLE}#{File.basename($0)}#{WHITE} [options] #{PURPLE}#{generator_group}#{WHITE} #{PURPLE}#{generator_type}#{WHITE} #{BLUE}<project-name>#{WHITE}"
|
103
|
+
opts.add_default(options = {})
|
104
|
+
opts.separator "#{BLUE}Please enter a project-name!#{WHITE}"
|
105
|
+
end
|
106
|
+
parser.parse(["-h"])
|
107
|
+
exit
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
metadata
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: lepidoptera
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Thomas Duerr
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2010-11-07 00:00:00 +01:00
|
18
|
+
default_executable: lep
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: rubigen
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
segments:
|
29
|
+
- 1
|
30
|
+
- 5
|
31
|
+
- 5
|
32
|
+
version: 1.5.5
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: git
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 1
|
45
|
+
- 2
|
46
|
+
- 5
|
47
|
+
version: 1.2.5
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: jeweler
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 1
|
60
|
+
- 4
|
61
|
+
- 0
|
62
|
+
version: 1.4.0
|
63
|
+
type: :development
|
64
|
+
version_requirements: *id003
|
65
|
+
description: Lepidoptera is a very simple and easy extensible code generator for common every day projects.
|
66
|
+
email: thomduerr@gmail.com
|
67
|
+
executables:
|
68
|
+
- lep
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files:
|
72
|
+
- README.md
|
73
|
+
files:
|
74
|
+
- .gitignore
|
75
|
+
- HISTORY.md
|
76
|
+
- README.md
|
77
|
+
- Rakefile
|
78
|
+
- bin/lep
|
79
|
+
- heroku_generators/sinatra/INFO
|
80
|
+
- heroku_generators/sinatra/sinatra_generator.rb
|
81
|
+
- heroku_generators/sinatra/templates/.gems
|
82
|
+
- heroku_generators/sinatra/templates/README.md
|
83
|
+
- heroku_generators/sinatra/templates/app.rb
|
84
|
+
- heroku_generators/sinatra/templates/config.ru
|
85
|
+
- heroku_generators/static/INFO
|
86
|
+
- heroku_generators/static/static_generator.rb
|
87
|
+
- heroku_generators/static/templates/README.md
|
88
|
+
- heroku_generators/static/templates/config.ru
|
89
|
+
- heroku_generators/static/templates/public/css/main.css
|
90
|
+
- heroku_generators/static/templates/public/index.html
|
91
|
+
- heroku_generators/static/templates/public/js/app.js
|
92
|
+
- jquery_generators/plugin/INFO
|
93
|
+
- jquery_generators/plugin/plugin_generator.rb
|
94
|
+
- jquery_generators/plugin/templates/demo.html
|
95
|
+
- jquery_generators/plugin/templates/js/jquery.plugin_name.js
|
96
|
+
- lepidoptera.gemspec
|
97
|
+
- lib/base.rb
|
98
|
+
- lib/butterfly.rb
|
99
|
+
- lib/options.rb
|
100
|
+
has_rdoc: true
|
101
|
+
homepage: http://github.com/thomd/lepidoptera/
|
102
|
+
licenses: []
|
103
|
+
|
104
|
+
post_install_message:
|
105
|
+
rdoc_options:
|
106
|
+
- --charset=UTF-8
|
107
|
+
require_paths:
|
108
|
+
- lib
|
109
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
segments:
|
115
|
+
- 0
|
116
|
+
version: "0"
|
117
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
118
|
+
none: false
|
119
|
+
requirements:
|
120
|
+
- - ">="
|
121
|
+
- !ruby/object:Gem::Version
|
122
|
+
segments:
|
123
|
+
- 0
|
124
|
+
version: "0"
|
125
|
+
requirements: []
|
126
|
+
|
127
|
+
rubyforge_project:
|
128
|
+
rubygems_version: 1.3.7
|
129
|
+
signing_key:
|
130
|
+
specification_version: 3
|
131
|
+
summary: a life-enhancing code generator for everyday use
|
132
|
+
test_files: []
|
133
|
+
|