seedling 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +3 -0
- data/CHANGELOG +76 -0
- data/MANIFEST +42 -0
- data/README +28 -0
- data/Rakefile +68 -0
- data/bin/seedling +15 -0
- data/lib/seedling.rb +5 -0
- data/lib/seedling/bin.rb +196 -0
- data/lib/seedling/extensions/inflector.rb +283 -0
- data/lib/seedling/project_creator.rb +147 -0
- data/lib/seedling/version.rb +3 -0
- data/lib/templates/core/Rakefile.seed +68 -0
- data/lib/templates/core/lib/library.rb.seed +5 -0
- data/lib/templates/core/lib/library/version.rb.seed +3 -0
- data/lib/templates/core/spec/helper.rb.seed +28 -0
- data/lib/templates/core/tasks/authors.rake +30 -0
- data/lib/templates/core/tasks/bacon.rake +70 -0
- data/lib/templates/core/tasks/changelog.rake +18 -0
- data/lib/templates/core/tasks/copyright.rake +21 -0
- data/lib/templates/core/tasks/gem.rake +23 -0
- data/lib/templates/core/tasks/gem_installer.rake +76 -0
- data/lib/templates/core/tasks/install_dependencies.rake +6 -0
- data/lib/templates/core/tasks/manifest.rake +4 -0
- data/lib/templates/core/tasks/rcov.rake +23 -0
- data/lib/templates/core/tasks/release.rake +52 -0
- data/lib/templates/core/tasks/reversion.rake +8 -0
- data/lib/templates/core/tasks/setup.rake.seed +15 -0
- data/seedling.gemspec +38 -0
- data/spec/helper.rb +28 -0
- data/tasks/authors.rake +30 -0
- data/tasks/bacon.rake +70 -0
- data/tasks/changelog.rake +18 -0
- data/tasks/copyright.rake +21 -0
- data/tasks/gem.rake +23 -0
- data/tasks/gem_installer.rake +76 -0
- data/tasks/install_dependencies.rake +6 -0
- data/tasks/manifest.rake +4 -0
- data/tasks/rcov.rake +23 -0
- data/tasks/release.rake +52 -0
- data/tasks/reversion.rake +8 -0
- data/tasks/setup.rake +15 -0
- data/tasks/yard.rake +4 -0
- metadata +101 -0
data/AUTHORS
ADDED
data/CHANGELOG
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
[db34e4f | Thu May 14 17:30:32 UTC 2009] Kevin Berry <kevin@opensourcealchemist.com>
|
2
|
+
|
3
|
+
* Correct Rakefile for project name, update manifest, authors.
|
4
|
+
|
5
|
+
[27deb65 | Thu May 14 15:30:14 UTC 2009] Kevin Berry <kevin@opensourcealchemist.com>
|
6
|
+
|
7
|
+
* Version 0.0.1
|
8
|
+
|
9
|
+
[4017044 | Thu May 14 14:50:26 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
10
|
+
|
11
|
+
* Remove old library dir, and correct erb output for library.rb.seed
|
12
|
+
|
13
|
+
[04d16e0 | Thu May 14 14:45:02 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
14
|
+
|
15
|
+
* Get the library module and children in the right place. TODO: Remove library directory from plant.
|
16
|
+
|
17
|
+
[25e0453 | Thu May 14 14:09:29 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
18
|
+
|
19
|
+
* Fix erb calls (Railsism doesn't work!)
|
20
|
+
|
21
|
+
[f8eeba5 | Wed May 13 18:55:39 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
22
|
+
|
23
|
+
* Add params for doc_generator, test_suite, correct email parameter.
|
24
|
+
|
25
|
+
[ead7fbf | Wed May 13 18:22:26 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
26
|
+
|
27
|
+
* Add rubyforge_project commandline option.
|
28
|
+
|
29
|
+
[fb7663b | Wed May 13 17:34:18 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
30
|
+
|
31
|
+
* Fix a couple of templates, and add more planting options.
|
32
|
+
|
33
|
+
[eb1d0d0 | Wed May 13 15:40:01 UTC 2009] Kevin Berry <kevinberry@nrs.us>
|
34
|
+
|
35
|
+
* Convert setup into a seed (erb) so that bacon/rspec and rdoc/yard choices can be made.
|
36
|
+
|
37
|
+
[771f9d3 | Tue May 12 23:12:42 UTC 2009] Kevin Berry <KevinBerry@nrs.us>
|
38
|
+
|
39
|
+
* rest of erb to seed conversion.
|
40
|
+
|
41
|
+
[72aa1b4 | Tue May 12 23:06:40 UTC 2009] Kevin Berry <KevinBerry@nrs.us>
|
42
|
+
|
43
|
+
* Adjust library.rb.erb to library.rb.seed, and adjust template data to match new standards.
|
44
|
+
|
45
|
+
[2f71f19 | Tue May 12 22:50:37 UTC 2009] TJ Vanderpoel <bougy.man@gmail.com>
|
46
|
+
|
47
|
+
* changed extension for templates to be parsed with erb to .seed to remove conflicts with actual .erb files. added most options to Rakefile.seed. TODO: finish out Rakefile.seed and move on to more .seed files where dynamic values are needed
|
48
|
+
|
49
|
+
[aff3223 | Mon May 11 19:41:52 UTC 2009] TJ Vanderpoel <bougyman@zero.(none)>
|
50
|
+
|
51
|
+
* added bin/seedling and began forming bin.rb to seedling usage
|
52
|
+
|
53
|
+
[6765184 | Sun May 10 22:32:16 UTC 2009] Kevin Berry <Kevin Berry>
|
54
|
+
|
55
|
+
* Modify Rakefile.erb to get some project info, need to get ProjectCreator to feed the right info.
|
56
|
+
|
57
|
+
[5917d53 | Sun May 10 03:42:26 UTC 2009] Kevin Berry <Kevin Berry>
|
58
|
+
|
59
|
+
* Make plant work.
|
60
|
+
|
61
|
+
[f02eaf1 | Sun May 10 03:06:22 UTC 2009] Kevin Berry <Kevin Berry>
|
62
|
+
|
63
|
+
* Bring in initial generator and ProjectCreator kit (stripped down bougyman's autumn library.)
|
64
|
+
|
65
|
+
[22fb2a5 | Fri May 08 03:19:21 UTC 2009] TJ Vanderpoel <bougy.man@gmail.com>
|
66
|
+
|
67
|
+
* changed env variable for versioning to VERSION
|
68
|
+
|
69
|
+
[6329710 | Fri May 08 03:07:50 UTC 2009] TJ Vanderpoel <bougy.man@gmail.com>
|
70
|
+
|
71
|
+
* added yard task and a README, plus a .gitignore
|
72
|
+
|
73
|
+
[41fd3c5 | Thu May 07 19:21:22 UTC 2009] TJ Vanderpoel <bougy.man@gmail.com>
|
74
|
+
|
75
|
+
* new tree to begin seedling work
|
76
|
+
|
data/MANIFEST
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
AUTHORS
|
2
|
+
CHANGELOG
|
3
|
+
MANIFEST
|
4
|
+
README
|
5
|
+
Rakefile
|
6
|
+
bin/seedling
|
7
|
+
lib/seedling.rb
|
8
|
+
lib/seedling/bin.rb
|
9
|
+
lib/seedling/extensions/inflector.rb
|
10
|
+
lib/seedling/project_creator.rb
|
11
|
+
lib/seedling/version.rb
|
12
|
+
lib/templates/core/Rakefile.seed
|
13
|
+
lib/templates/core/lib/library.rb.seed
|
14
|
+
lib/templates/core/lib/library/version.rb.seed
|
15
|
+
lib/templates/core/spec/helper.rb.seed
|
16
|
+
lib/templates/core/tasks/authors.rake
|
17
|
+
lib/templates/core/tasks/bacon.rake
|
18
|
+
lib/templates/core/tasks/changelog.rake
|
19
|
+
lib/templates/core/tasks/copyright.rake
|
20
|
+
lib/templates/core/tasks/gem.rake
|
21
|
+
lib/templates/core/tasks/gem_installer.rake
|
22
|
+
lib/templates/core/tasks/install_dependencies.rake
|
23
|
+
lib/templates/core/tasks/manifest.rake
|
24
|
+
lib/templates/core/tasks/rcov.rake
|
25
|
+
lib/templates/core/tasks/release.rake
|
26
|
+
lib/templates/core/tasks/reversion.rake
|
27
|
+
lib/templates/core/tasks/setup.rake.seed
|
28
|
+
seedling.gemspec
|
29
|
+
spec/helper.rb
|
30
|
+
tasks/authors.rake
|
31
|
+
tasks/bacon.rake
|
32
|
+
tasks/changelog.rake
|
33
|
+
tasks/copyright.rake
|
34
|
+
tasks/gem.rake
|
35
|
+
tasks/gem_installer.rake
|
36
|
+
tasks/install_dependencies.rake
|
37
|
+
tasks/manifest.rake
|
38
|
+
tasks/rcov.rake
|
39
|
+
tasks/release.rake
|
40
|
+
tasks/reversion.rake
|
41
|
+
tasks/setup.rake
|
42
|
+
tasks/yard.rake
|
data/README
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
==Seedling
|
2
|
+
----------
|
3
|
+
|
4
|
+
Seedling is a tool for creating ruby projects. It aims to add
|
5
|
+
tasks (via a Rakefile and some tasks/*.rake) which allow for quick
|
6
|
+
and easy publishing of your new ruby library, via github and or rubyforge.
|
7
|
+
It automates some of the monotony such as
|
8
|
+
|
9
|
+
* Re-Versioning
|
10
|
+
* AUTHORS updating
|
11
|
+
* .gemspec updates
|
12
|
+
* building a gem, tarball, zip, source export tree
|
13
|
+
* Test (spec) running, via a bacon task and bacon spec helper (we love bacon)
|
14
|
+
* Documentation via yard
|
15
|
+
* CHANGELOG updating
|
16
|
+
|
17
|
+
== Download
|
18
|
+
|
19
|
+
using git
|
20
|
+
git clone git://rubyists.com/gits/seedling
|
21
|
+
|
22
|
+
==Usage
|
23
|
+
-------
|
24
|
+
|
25
|
+
We're getting there. Will be
|
26
|
+
seedling plant /path/to/tree
|
27
|
+
|
28
|
+
Copyright(c) 2009 The Rubyists
|
data/Rakefile
ADDED
@@ -0,0 +1,68 @@
|
|
1
|
+
begin; require 'rubygems'; rescue LoadError; end
|
2
|
+
|
3
|
+
require 'rake'
|
4
|
+
require 'rake/clean'
|
5
|
+
require 'rake/gempackagetask'
|
6
|
+
require 'time'
|
7
|
+
require 'date'
|
8
|
+
require "lib/seedling"
|
9
|
+
|
10
|
+
PROJECT_SPECS = FileList[
|
11
|
+
'spec/**/*.rb'
|
12
|
+
]
|
13
|
+
|
14
|
+
PROJECT_MODULE = 'Seedling'
|
15
|
+
PROJECT_README = 'README'
|
16
|
+
PROJECT_RUBYFORGE_GROUP_ID = 4525
|
17
|
+
PROJECT_COPYRIGHT = [
|
18
|
+
"# Copyright (c) #{Time.now.year} The Rubyists rubyists@rubyists.com",
|
19
|
+
"# Distributed under the terms of the MIT license."
|
20
|
+
]
|
21
|
+
|
22
|
+
# To release the monthly version do:
|
23
|
+
# $ PROJECT_VERSION=2009.03 rake release
|
24
|
+
IGNORE_FILES = [/\.gitignore/]
|
25
|
+
|
26
|
+
GEMSPEC = Gem::Specification.new{|s|
|
27
|
+
s.name = 'seedling'
|
28
|
+
s.author = "Kevin Berry"
|
29
|
+
s.summary = "A lightweight tool to create new ruby library trees, with helpers to make gemming and maintaining a breeze."
|
30
|
+
s.description = s.summary
|
31
|
+
s.email = 'deathsyn@gmail.com'
|
32
|
+
s.homepage = 'http://github.com/deathsyn/seedling'
|
33
|
+
s.platform = Gem::Platform::RUBY
|
34
|
+
s.version = (ENV['VERSION'] || (begin;Object.const_get(PROJECT_MODULE)::VERSION;rescue;Date.today.strftime("%Y.%m.%d");end))
|
35
|
+
s.files = `git ls-files`.split("\n").sort.reject { |f| IGNORE_FILES.detect { |exp| f.match(exp) } }
|
36
|
+
s.has_rdoc = true
|
37
|
+
s.require_path = 'lib'
|
38
|
+
s.bindir = "bin"
|
39
|
+
s.executables = ["seedling"]
|
40
|
+
s.rubyforge_project = "seedling"
|
41
|
+
|
42
|
+
s.post_install_message = <<MESSAGE.strip
|
43
|
+
============================================================
|
44
|
+
|
45
|
+
Thank you for installing Seedling!
|
46
|
+
Begin by planting your ruby project with
|
47
|
+
# seedling plant /path/to/new/project
|
48
|
+
|
49
|
+
============================================================
|
50
|
+
MESSAGE
|
51
|
+
}
|
52
|
+
|
53
|
+
Dir['tasks/*.rake'].each{|f| import(f) }
|
54
|
+
|
55
|
+
task :default => [:bacon]
|
56
|
+
|
57
|
+
CLEAN.include %w[
|
58
|
+
**/.*.sw?
|
59
|
+
*.gem
|
60
|
+
.config
|
61
|
+
**/*~
|
62
|
+
**/{data.db,cache.yaml}
|
63
|
+
*.yaml
|
64
|
+
pkg
|
65
|
+
rdoc
|
66
|
+
ydoc
|
67
|
+
*coverage*
|
68
|
+
]
|
data/bin/seedling
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
begin
|
3
|
+
require "pathname"
|
4
|
+
local_seedling = Pathname.new(__FILE__).expand_path.dirname.join("..", "lib", "seedling.rb")
|
5
|
+
if local_seedling.file?
|
6
|
+
require local_seedling
|
7
|
+
else
|
8
|
+
require "seedling"
|
9
|
+
end
|
10
|
+
require "seedling/bin"
|
11
|
+
rescue LoadError
|
12
|
+
require "rubygems"
|
13
|
+
require "seedling/bin"
|
14
|
+
end
|
15
|
+
Seedling::Bin::Cmd.run(ARGV)
|
data/lib/seedling.rb
ADDED
data/lib/seedling/bin.rb
ADDED
@@ -0,0 +1,196 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require "seedling/extensions/inflector"
|
4
|
+
### This module offers the functionality to create.
|
5
|
+
module Seedling
|
6
|
+
module Bin
|
7
|
+
class Cmd # This class contains the command methods {{{
|
8
|
+
#include Helpers
|
9
|
+
attr_accessor :command
|
10
|
+
|
11
|
+
def initialize(args = nil)
|
12
|
+
args ||= ARGV
|
13
|
+
raise "arguments must be an array!" unless args.respond_to?(:detect)
|
14
|
+
@ourargs = args.dup
|
15
|
+
@command = args.detect { |arg| arg.match(/^(?:--?)?(?:plant|create|h(?:elp)?|v(?:ersion)?|console)/) }
|
16
|
+
if command.nil?
|
17
|
+
@command = ""
|
18
|
+
else
|
19
|
+
args.delete(@command)
|
20
|
+
end
|
21
|
+
ARGV.replace(args)
|
22
|
+
end
|
23
|
+
|
24
|
+
# {{{ #run is called when we're interactive ($0 == __FILE__)
|
25
|
+
def self.run(args = nil)
|
26
|
+
cmd = new(args)
|
27
|
+
case cmd.command
|
28
|
+
when /^(?:--?)?(?:plant|create)$/
|
29
|
+
require "seedling/project_creator"
|
30
|
+
cmd.plant(cmd.command)
|
31
|
+
when /^(?:--?)?console$/
|
32
|
+
require "irb"
|
33
|
+
require "irb/completion"
|
34
|
+
cmd.include_seedling
|
35
|
+
IRB.start
|
36
|
+
puts "Seedling session has ended."
|
37
|
+
when /^(?:--?)?h(elp)?$/
|
38
|
+
puts cmd.usage
|
39
|
+
when /^(?:--?)?v(ersion)?$/
|
40
|
+
cmd.include_seedling
|
41
|
+
puts Seedling::VERSION
|
42
|
+
exit
|
43
|
+
when /^$/
|
44
|
+
puts "Must supply a valid command"
|
45
|
+
puts cmd.usage
|
46
|
+
exit 1
|
47
|
+
else
|
48
|
+
puts "#{command} not implemented"
|
49
|
+
puts cmd.usage
|
50
|
+
exit 1
|
51
|
+
end
|
52
|
+
end # }}}
|
53
|
+
|
54
|
+
def include_seedling # {{{
|
55
|
+
begin
|
56
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), '/../lib')
|
57
|
+
require 'seedling'
|
58
|
+
rescue LoadError
|
59
|
+
$LOAD_PATH.shift
|
60
|
+
|
61
|
+
begin
|
62
|
+
require 'rubygems'
|
63
|
+
rescue LoadError
|
64
|
+
end
|
65
|
+
require 'seedling'
|
66
|
+
end
|
67
|
+
end # }}}
|
68
|
+
|
69
|
+
def usage # {{{
|
70
|
+
txt = [
|
71
|
+
"\n Usage:",
|
72
|
+
"seedling <plant|create|console> PROJECT [options]\n",
|
73
|
+
"Commands:\n",
|
74
|
+
" plant - Creates a new prototype Seedling application in a directory named PROJECT in",
|
75
|
+
" the current directory. seedling create foo would make ./foo containing a",
|
76
|
+
" seedling prototype.\n",
|
77
|
+
" create - Synonymous with plant.\n",
|
78
|
+
" console - Starts an irb console with seedling (and irb completion) loaded.",
|
79
|
+
" ARGV is passed on to IRB.\n\n"
|
80
|
+
].join("\n\t")
|
81
|
+
|
82
|
+
txt << "* All commands take PROJECT as the directory the seedling lives in.\n\n"
|
83
|
+
txt << plant_options.to_s << "\n"
|
84
|
+
#if is_windows?
|
85
|
+
#txt << %x{ruby #{rackup_path} --help}.split("\n").reject { |line| line.match(/^Usage:/) }.join("\n\t")
|
86
|
+
#else
|
87
|
+
#txt << %x{#{rackup_path} --help}.split("\n").reject { |line| line.match(/^Usage:/) }.join("\n\t")
|
88
|
+
#end
|
89
|
+
end # }}}
|
90
|
+
|
91
|
+
def al_root
|
92
|
+
require "pathname"
|
93
|
+
dir = nil
|
94
|
+
if ARGV.size == 1
|
95
|
+
dir = Pathname.new(ARGV.shift)
|
96
|
+
elsif ARGV.size > 1
|
97
|
+
$stderr.puts "Unknown options given #{ARGV.join(" ")}"
|
98
|
+
puts usage
|
99
|
+
exit 1
|
100
|
+
end
|
101
|
+
if dir.nil? or not dir.directory?
|
102
|
+
dir = Pathname.new(ENV["PWD"]).expand_path
|
103
|
+
$stderr.puts "Path to seedling tree not given or invalid, using #{dir}"
|
104
|
+
end
|
105
|
+
Object.const_set("AL_ROOT", dir.expand_path.to_s)
|
106
|
+
Dir.chdir(AL_ROOT)
|
107
|
+
end
|
108
|
+
|
109
|
+
### Methods for commands {{{
|
110
|
+
def plant_options(opts = {})
|
111
|
+
@plant_opts ||= OptionParser.new do |o|
|
112
|
+
o.banner = "Planting Options"
|
113
|
+
o.on("-nSUMMARY", "--summary SUMMARY", "Short description of this project") { |yn| opts[:summary] = yn }
|
114
|
+
o.on("-dDESCRIPTION", "--description DESCRIPTION", "Longer description (Default: summary)") { |des| opts[:description] = des }
|
115
|
+
o.on("-lLIBNAME", "--libname LIBNAME", "Library name (Default: path specifcation)") { |libname| opts[:lib_name] = libname }
|
116
|
+
o.on("-gDOCGENERATOR", "--doc-generator DOCGENERATOR", "Preferred documentation generator (Default: yard)") { |docgenerator| opts[:doc_generator] = docgenerator }
|
117
|
+
o.on("-tTESTSUITE", "--test-suite TESTSUITE", "Preferred test suite (Default: bacon)") { |testsuite| opts[:test_suite] = testsuite }
|
118
|
+
o.on("-vVER", "--version VER", "Initial version number (Default: 0.0.1)") { |ver| opts[:version] = ver }
|
119
|
+
o.on("-rRUBYFORGE", "--rubyforge RUBYFORGE", "Rubyforge project name") { |rubyforge| opts[:rubyforge_project] = rubyforge }
|
120
|
+
|
121
|
+
o.separator ""
|
122
|
+
o.separator "Author Options"
|
123
|
+
o.on("-sAUTHOR", "--summary AUTHOR", "Author's Name") { |yn| opts[:author_name] = yn }
|
124
|
+
o.on("-eEMAIL", "--email EMAIL", "Author's Email") { |yn| opts[:author_email] = yn }
|
125
|
+
o.on("-uURL", "--url URL", "Project URL/homepage") { |url| opts[:project_url] = url }
|
126
|
+
|
127
|
+
o.separator ""
|
128
|
+
o.separator "Directory Creation Options"
|
129
|
+
o.on("-f", "--force", "Force creation if dir already exists") { |yn| opts[:force] = true }
|
130
|
+
o.on("-a", "--amend", "Update a tree") { |yn| opts[:amend] = true }
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def plant(command) # {{{
|
135
|
+
plant_options(o = {}).parse!(ARGV)
|
136
|
+
unless ARGV.size == 1
|
137
|
+
$stderr.puts "Invalid options given: #{ARGV.join(" ")}"
|
138
|
+
exit 1
|
139
|
+
end
|
140
|
+
project_root = ARGV.shift
|
141
|
+
if project_root.nil?
|
142
|
+
$stderr.puts "Must supply a valid directory to install your project, you gave none."
|
143
|
+
puts usage
|
144
|
+
exit 1
|
145
|
+
end
|
146
|
+
o[:lib_name] ||= Pathname.new(project_root).basename.to_s.classify
|
147
|
+
o[:lib_name_u] ||= o[:lib_name].underscore
|
148
|
+
opts = plant_defaults(o)
|
149
|
+
# need to titleize this
|
150
|
+
include_seedling
|
151
|
+
Seedling::ProjectCreator.new(project_root, opts).create
|
152
|
+
end # }}}
|
153
|
+
|
154
|
+
private
|
155
|
+
|
156
|
+
# Sets all of our default settings to make a sane rakefile, pulling from everywhere that makes sense
|
157
|
+
def plant_defaults(o = {:lib_name => "Seedling"})
|
158
|
+
# this shouldn't happen, but if so let's be descriptive
|
159
|
+
raise "plant_defaults requires a :lib_name in the calling argument" unless o[:lib_name]
|
160
|
+
o[:lib_name_u] = o[:lib_name].underscore
|
161
|
+
[:author_name, :author_email].each do |opt|
|
162
|
+
o[opt] = self.send(opt)
|
163
|
+
end
|
164
|
+
o[:summary] ||= "The #{o[:lib_name].classify.titleize} library, by #{o[:author_name]}"
|
165
|
+
o[:description] ||= o[:summary]
|
166
|
+
o[:version] ||= "0.0.1"
|
167
|
+
o[:test_suite] ||= "bacon"
|
168
|
+
o[:doc_generator] ||= "yard"
|
169
|
+
o
|
170
|
+
end
|
171
|
+
|
172
|
+
def author_email
|
173
|
+
gitted = %x{git config --global --get user.email}
|
174
|
+
return gitted.to_s.strip if gitted.to_s.match(/\w/)
|
175
|
+
return ENV["EMAIL"] if ENV["EMAIL"]
|
176
|
+
return [ENV["LOGUSER"], ENV["HOSTNAME"]].join("@") if ENV["LOGUSER"] and ENV["HOSTNAME"]
|
177
|
+
raise "Cannot find author email, please use --email \"you@your.domain.com\" or set the EMAIL environment variable"
|
178
|
+
end
|
179
|
+
|
180
|
+
def author_name
|
181
|
+
gitted = %x{git config --global --get user.name}
|
182
|
+
return gitted.to_s.strip if gitted.to_s.match(/\w/)
|
183
|
+
return ENV["NAME"] if ENV["NAME"]
|
184
|
+
return ENV["LOGUSER"] if ENV["LOGUSER"]
|
185
|
+
return Pathname.new(ENV["HOME"]).expand_path.basename.to_s if ENV["HOME"]
|
186
|
+
raise "Cannot find author name, please use --author \"Your Name\" or set the NAME or LOGUSER environment variables"
|
187
|
+
end
|
188
|
+
|
189
|
+
### End of command methods }}}
|
190
|
+
end # }}}
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
if $0 == __FILE__
|
195
|
+
Seedling::Bin::Cmd.run(ARGV)
|
196
|
+
end
|
@@ -0,0 +1,283 @@
|
|
1
|
+
# Add inflection methods to String, which allows the easy transformation of
|
2
|
+
# words from singular to plural,class names to table names, modularized class
|
3
|
+
# names to ones without, and class names to foreign keys.
|
4
|
+
|
5
|
+
class String
|
6
|
+
# This module acts as a singleton returned/yielded by String.inflections,
|
7
|
+
# which is used to override or specify additional inflection rules. Examples:
|
8
|
+
#
|
9
|
+
# String.inflections do |inflect|
|
10
|
+
# inflect.plural /^(ox)$/i, '\1\2en'
|
11
|
+
# inflect.singular /^(ox)en/i, '\1'
|
12
|
+
#
|
13
|
+
# inflect.irregular 'octopus', 'octopi'
|
14
|
+
#
|
15
|
+
# inflect.uncountable "equipment"
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# New rules are added at the top. So in the example above, the irregular rule for octopus will now be the first of the
|
19
|
+
# pluralization and singularization rules that is runs. This guarantees that your rules run before any of the rules that may
|
20
|
+
# already have been loaded.
|
21
|
+
module Inflections
|
22
|
+
@plurals, @singulars, @uncountables = [], [], []
|
23
|
+
|
24
|
+
class << self
|
25
|
+
attr_reader :plurals, :singulars, :uncountables
|
26
|
+
end
|
27
|
+
|
28
|
+
# Clears the loaded inflections within a given scope (default is :all). Give the scope as a symbol of the inflection type,
|
29
|
+
# the options are: :plurals, :singulars, :uncountables
|
30
|
+
#
|
31
|
+
# Examples:
|
32
|
+
# clear :all
|
33
|
+
# clear :plurals
|
34
|
+
def self.clear(scope = :all)
|
35
|
+
case scope
|
36
|
+
when :all
|
37
|
+
@plurals, @singulars, @uncountables = [], [], []
|
38
|
+
else
|
39
|
+
instance_variable_set("@#{scope}", [])
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Specifies a new irregular that applies to both pluralization and singularization at the same time. This can only be used
|
44
|
+
# for strings, not regular expressions. You simply pass the irregular in singular and plural form.
|
45
|
+
#
|
46
|
+
# Examples:
|
47
|
+
# irregular 'octopus', 'octopi'
|
48
|
+
# irregular 'person', 'people'
|
49
|
+
def self.irregular(singular, plural)
|
50
|
+
plural(Regexp.new("(#{singular[0,1]})#{singular[1..-1]}$", "i"), '\1' + plural[1..-1])
|
51
|
+
singular(Regexp.new("(#{plural[0,1]})#{plural[1..-1]}$", "i"), '\1' + singular[1..-1])
|
52
|
+
end
|
53
|
+
|
54
|
+
# Specifies a new pluralization rule and its replacement. The rule can either be a string or a regular expression.
|
55
|
+
# The replacement should always be a string that may include references to the matched data from the rule.
|
56
|
+
#
|
57
|
+
# Example:
|
58
|
+
# plural(/(x|ch|ss|sh)$/i, '\1es')
|
59
|
+
def self.plural(rule, replacement)
|
60
|
+
@plurals.insert(0, [rule, replacement])
|
61
|
+
end
|
62
|
+
|
63
|
+
# Specifies a new singularization rule and its replacement. The rule can either be a string or a regular expression.
|
64
|
+
# The replacement should always be a string that may include references to the matched data from the rule.
|
65
|
+
#
|
66
|
+
# Example:
|
67
|
+
# singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
68
|
+
def self.singular(rule, replacement)
|
69
|
+
@singulars.insert(0, [rule, replacement])
|
70
|
+
end
|
71
|
+
|
72
|
+
# Add uncountable words that shouldn't be attempted inflected.
|
73
|
+
#
|
74
|
+
# Examples:
|
75
|
+
# uncountable "money"
|
76
|
+
# uncountable "money", "information"
|
77
|
+
# uncountable %w( money information rice )
|
78
|
+
def self.uncountable(*words)
|
79
|
+
(@uncountables << words).flatten!
|
80
|
+
end
|
81
|
+
|
82
|
+
# Setup the default inflections
|
83
|
+
plural(/$/, 's')
|
84
|
+
plural(/s$/i, 's')
|
85
|
+
plural(/(ax|test)is$/i, '\1es')
|
86
|
+
plural(/(octop|vir)us$/i, '\1i')
|
87
|
+
plural(/(alias|status)$/i, '\1es')
|
88
|
+
plural(/(bu)s$/i, '\1ses')
|
89
|
+
plural(/(buffal|tomat)o$/i, '\1oes')
|
90
|
+
plural(/([ti])um$/i, '\1a')
|
91
|
+
plural(/sis$/i, 'ses')
|
92
|
+
plural(/(?:([^f])fe|([lr])f)$/i, '\1\2ves')
|
93
|
+
plural(/(hive)$/i, '\1s')
|
94
|
+
plural(/([^aeiouy]|qu)y$/i, '\1ies')
|
95
|
+
plural(/(x|ch|ss|sh)$/i, '\1es')
|
96
|
+
plural(/(matr|vert|ind)ix|ex$/i, '\1ices')
|
97
|
+
plural(/([m|l])ouse$/i, '\1ice')
|
98
|
+
plural(/^(ox)$/i, '\1en')
|
99
|
+
plural(/(quiz)$/i, '\1zes')
|
100
|
+
|
101
|
+
singular(/s$/i, '')
|
102
|
+
singular(/(n)ews$/i, '\1ews')
|
103
|
+
singular(/([ti])a$/i, '\1um')
|
104
|
+
singular(/((a)naly|(b)a|(d)iagno|(p)arenthe|(p)rogno|(s)ynop|(t)he)ses$/i, '\1\2sis')
|
105
|
+
singular(/(^analy)ses$/i, '\1sis')
|
106
|
+
singular(/([^f])ves$/i, '\1fe')
|
107
|
+
singular(/(hive)s$/i, '\1')
|
108
|
+
singular(/(tive)s$/i, '\1')
|
109
|
+
singular(/([lr])ves$/i, '\1f')
|
110
|
+
singular(/([^aeiouy]|qu)ies$/i, '\1y')
|
111
|
+
singular(/(s)eries$/i, '\1eries')
|
112
|
+
singular(/(m)ovies$/i, '\1ovie')
|
113
|
+
singular(/(x|ch|ss|sh)es$/i, '\1')
|
114
|
+
singular(/([m|l])ice$/i, '\1ouse')
|
115
|
+
singular(/(bus)es$/i, '\1')
|
116
|
+
singular(/(o)es$/i, '\1')
|
117
|
+
singular(/(shoe)s$/i, '\1')
|
118
|
+
singular(/(cris|ax|test)es$/i, '\1is')
|
119
|
+
singular(/(octop|vir)i$/i, '\1us')
|
120
|
+
singular(/(alias|status)es$/i, '\1')
|
121
|
+
singular(/^(ox)en/i, '\1')
|
122
|
+
singular(/(vert|ind)ices$/i, '\1ex')
|
123
|
+
singular(/(matr)ices$/i, '\1ix')
|
124
|
+
singular(/(quiz)zes$/i, '\1')
|
125
|
+
|
126
|
+
irregular('person', 'people')
|
127
|
+
irregular('man', 'men')
|
128
|
+
irregular('child', 'children')
|
129
|
+
irregular('sex', 'sexes')
|
130
|
+
irregular('move', 'moves')
|
131
|
+
|
132
|
+
uncountable(%w(equipment information rice money species series fish sheep))
|
133
|
+
end
|
134
|
+
|
135
|
+
# Yield the Inflections module if a block is given, and return
|
136
|
+
# the Inflections module.
|
137
|
+
def self.inflections
|
138
|
+
yield Inflections if block_given?
|
139
|
+
Inflections
|
140
|
+
end
|
141
|
+
|
142
|
+
# By default, camelize converts the string to UpperCamelCase. If the argument to camelize
|
143
|
+
# is set to :lower then camelize produces lowerCamelCase.
|
144
|
+
#
|
145
|
+
# camelize will also convert '/' to '::' which is useful for converting paths to namespaces
|
146
|
+
#
|
147
|
+
# Examples
|
148
|
+
# "active_record".camelize #=> "ActiveRecord"
|
149
|
+
# "active_record".camelize(:lower) #=> "activeRecord"
|
150
|
+
# "active_record/errors".camelize #=> "ActiveRecord::Errors"
|
151
|
+
# "active_record/errors".camelize(:lower) #=> "activeRecord::Errors"
|
152
|
+
def camelize(first_letter_in_uppercase = :upper)
|
153
|
+
s = gsub(/\/(.?)/){|x| "::#{x[-1..-1].upcase unless x == '/'}"}.gsub(/(^|_)(.)/){|x| x[-1..-1].upcase}
|
154
|
+
s[0...1] = s[0...1].downcase unless first_letter_in_uppercase == :upper
|
155
|
+
s
|
156
|
+
end
|
157
|
+
alias_method :camelcase, :camelize
|
158
|
+
|
159
|
+
# Singularizes and camelizes the string. Also strips out all characters preceding
|
160
|
+
# and including a period (".").
|
161
|
+
#
|
162
|
+
# Examples
|
163
|
+
# "egg_and_hams".classify #=> "EggAndHam"
|
164
|
+
# "post".classify #=> "Post"
|
165
|
+
# "schema.post".classify #=> "Post"
|
166
|
+
def classify
|
167
|
+
sub(/.*\./, '').singularize.camelize
|
168
|
+
end
|
169
|
+
|
170
|
+
# Constantize tries to find a declared constant with the name specified
|
171
|
+
# in the string. It raises a NameError when the name is not in CamelCase
|
172
|
+
# or is not initialized.
|
173
|
+
#
|
174
|
+
# Examples
|
175
|
+
# "Module".constantize #=> Module
|
176
|
+
# "Class".constantize #=> Class
|
177
|
+
def constantize
|
178
|
+
raise(NameError, "#{inspect} is not a valid constant name!") unless m = /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/.match(self)
|
179
|
+
Object.module_eval("::#{m[1]}", __FILE__, __LINE__)
|
180
|
+
end
|
181
|
+
|
182
|
+
# Replaces underscores with dashes in the string.
|
183
|
+
#
|
184
|
+
# Example
|
185
|
+
# "puni_puni".dasherize #=> "puni-puni"
|
186
|
+
def dasherize
|
187
|
+
gsub(/_/, '-')
|
188
|
+
end
|
189
|
+
|
190
|
+
# Removes the module part from the expression in the string
|
191
|
+
#
|
192
|
+
# Examples
|
193
|
+
# "ActiveRecord::CoreExtensions::String::Inflections".demodulize #=> "Inflections"
|
194
|
+
# "Inflections".demodulize #=> "Inflections"
|
195
|
+
def demodulize
|
196
|
+
gsub(/^.*::/, '')
|
197
|
+
end
|
198
|
+
|
199
|
+
# Creates a foreign key name from a class name.
|
200
|
+
# +use_underscore+ sets whether the method should put '_' between the name and 'id'.
|
201
|
+
#
|
202
|
+
# Examples
|
203
|
+
# "Message".foreign_key #=> "message_id"
|
204
|
+
# "Message".foreign_key(false) #=> "messageid"
|
205
|
+
# "Admin::Post".foreign_key #=> "post_id"
|
206
|
+
def foreign_key(use_underscore = true)
|
207
|
+
"#{demodulize.underscore}#{'_' if use_underscore}id"
|
208
|
+
end
|
209
|
+
|
210
|
+
# Capitalizes the first word and turns underscores into spaces and strips _id.
|
211
|
+
# Like titleize, this is meant for creating pretty output.
|
212
|
+
#
|
213
|
+
# Examples
|
214
|
+
# "employee_salary" #=> "Employee salary"
|
215
|
+
# "author_id" #=> "Author"
|
216
|
+
def humanize
|
217
|
+
gsub(/_id$/, "").gsub(/_/, " ").capitalize
|
218
|
+
end
|
219
|
+
|
220
|
+
# Returns the plural form of the word in the string.
|
221
|
+
#
|
222
|
+
# Examples
|
223
|
+
# "post".pluralize #=> "posts"
|
224
|
+
# "octopus".pluralize #=> "octopi"
|
225
|
+
# "sheep".pluralize #=> "sheep"
|
226
|
+
# "words".pluralize #=> "words"
|
227
|
+
# "the blue mailman".pluralize #=> "the blue mailmen"
|
228
|
+
# "CamelOctopus".pluralize #=> "CamelOctopi"
|
229
|
+
def pluralize
|
230
|
+
result = dup
|
231
|
+
Inflections.plurals.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(downcase)
|
232
|
+
result
|
233
|
+
end
|
234
|
+
|
235
|
+
# The reverse of pluralize, returns the singular form of a word in a string.
|
236
|
+
#
|
237
|
+
# Examples
|
238
|
+
# "posts".singularize #=> "post"
|
239
|
+
# "octopi".singularize #=> "octopus"
|
240
|
+
# "sheep".singluarize #=> "sheep"
|
241
|
+
# "word".singluarize #=> "word"
|
242
|
+
# "the blue mailmen".singularize #=> "the blue mailman"
|
243
|
+
# "CamelOctopi".singularize #=> "CamelOctopus"
|
244
|
+
def singularize
|
245
|
+
result = dup
|
246
|
+
Inflections.singulars.each{|(rule, replacement)| break if result.gsub!(rule, replacement)} unless Inflections.uncountables.include?(downcase)
|
247
|
+
result
|
248
|
+
end
|
249
|
+
|
250
|
+
# Underscores and pluralizes the string.
|
251
|
+
#
|
252
|
+
# Examples
|
253
|
+
# "RawScaledScorer".tableize #=> "raw_scaled_scorers"
|
254
|
+
# "egg_and_ham".tableize #=> "egg_and_hams"
|
255
|
+
# "fancyCategory".tableize #=> "fancy_categories"
|
256
|
+
def tableize
|
257
|
+
underscore.pluralize
|
258
|
+
end
|
259
|
+
|
260
|
+
# Capitalizes all the words and replaces some characters in the string to create
|
261
|
+
# a nicer looking title. Titleize is meant for creating pretty output.
|
262
|
+
#
|
263
|
+
# titleize is also aliased as as titlecase
|
264
|
+
#
|
265
|
+
# Examples
|
266
|
+
# "man from the boondocks".titleize #=> "Man From The Boondocks"
|
267
|
+
# "x-men: the last stand".titleize #=> "X Men: The Last Stand"
|
268
|
+
def titleize
|
269
|
+
underscore.humanize.gsub(/\b([a-z])/){|x| x[-1..-1].upcase}
|
270
|
+
end
|
271
|
+
alias_method :titlecase, :titleize
|
272
|
+
|
273
|
+
# The reverse of camelize. Makes an underscored form from the expression in the string.
|
274
|
+
# Also changes '::' to '/' to convert namespaces to paths.
|
275
|
+
#
|
276
|
+
# Examples
|
277
|
+
# "ActiveRecord".underscore #=> "active_record"
|
278
|
+
# "ActiveRecord::Errors".underscore #=> active_record/errors
|
279
|
+
def underscore
|
280
|
+
gsub(/::/, '/').gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
281
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').tr("-", "_").downcase
|
282
|
+
end
|
283
|
+
end
|