prigner 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +248 -0
- data/COPYING +21 -0
- data/README.mkd +90 -0
- data/Rakefile +211 -0
- data/bin/prign +65 -0
- data/lib/prigner/builder.rb +51 -0
- data/lib/prigner/cli/copy.rb +0 -0
- data/lib/prigner/cli/list.rb +54 -0
- data/lib/prigner/cli/new.rb +96 -0
- data/lib/prigner/cli.rb +102 -0
- data/lib/prigner/extensions.rb +67 -0
- data/lib/prigner/model.rb +97 -0
- data/lib/prigner/project.rb +71 -0
- data/lib/prigner/template.rb +148 -0
- data/lib/prigner.rb +186 -0
- data/prigner.gemspec +120 -0
- data/share/templates/ruby/default/models/CHANGELOG +13 -0
- data/share/templates/ruby/default/models/COPYING +21 -0
- data/share/templates/ruby/default/models/README.rdoc +4 -0
- data/share/templates/ruby/default/models/module.rb +5 -0
- data/share/templates/ruby/default/specfile +16 -0
- data/share/templates/ruby/gem/models/CHANGELOG +13 -0
- data/share/templates/ruby/gem/models/COPYING +21 -0
- data/share/templates/ruby/gem/models/README.mkd +5 -0
- data/share/templates/ruby/gem/models/Rakefile +213 -0
- data/share/templates/ruby/gem/models/empty_test.rb +16 -0
- data/share/templates/ruby/gem/models/gemspec +67 -0
- data/share/templates/ruby/gem/models/module.rb +71 -0
- data/share/templates/ruby/gem/specfile +20 -0
- data/test/builder_test.rb +38 -0
- data/test/fixtures/model.rb.erb +12 -0
- data/test/fixtures/templates/shared/ruby/default/README.mkd +2 -0
- data/test/fixtures/templates/shared/ruby/default/models/README.mkd +2 -0
- data/test/fixtures/templates/shared/ruby/default/models/Rakefile +7 -0
- data/test/fixtures/templates/shared/ruby/default/models/empty_test.rb +21 -0
- data/test/fixtures/templates/shared/ruby/default/models/module.rb +6 -0
- data/test/fixtures/templates/shared/ruby/default/specfile +18 -0
- data/test/fixtures/templates/user/bash/default/specfile +0 -0
- data/test/fixtures/templates/user/ruby/program/models/README.erb +2 -0
- data/test/fixtures/templates/user/ruby/program/models/cli.rb.erb +5 -0
- data/test/fixtures/templates/user/ruby/program/models/module.rb.erb +6 -0
- data/test/fixtures/templates/user/ruby/program/models/program.rb.erb +3 -0
- data/test/fixtures/templates/user/ruby/program/specfile +18 -0
- data/test/fixtures/templates/user/vim/default/specfile +0 -0
- data/test/fixtures/templates/user/vim/plugin/specfile +0 -0
- data/test/fixtures/templates/user/vim/syntax/specfile +0 -0
- data/test/helpers.rb +22 -0
- data/test/model_test.rb +82 -0
- data/test/project_test.rb +46 -0
- data/test/spec_test.rb +64 -0
- data/test/template_test.rb +88 -0
- metadata +142 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
# Copyright (c) 2010 Codigorama, Hallison Batista
|
2
|
+
|
3
|
+
require "prigner"
|
4
|
+
|
5
|
+
program = :prign
|
6
|
+
command = File.basename(__FILE__, ".rb")
|
7
|
+
@options = {}
|
8
|
+
|
9
|
+
def templates_by_namespace(indent)
|
10
|
+
templates = Prigner::Template.all
|
11
|
+
message = []
|
12
|
+
templates.map do |namespace, list|
|
13
|
+
message << "* #{namespace}"
|
14
|
+
list.map do |template|
|
15
|
+
message << ("#{indent}> %-16s %s" % [template.name, template.spec.description])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
message.join("\n")
|
19
|
+
end
|
20
|
+
|
21
|
+
def show(message)
|
22
|
+
puts "#{Prigner::Version}"
|
23
|
+
puts "\n#{message}"
|
24
|
+
end
|
25
|
+
|
26
|
+
begin
|
27
|
+
|
28
|
+
ARGV.options do |arguments|
|
29
|
+
|
30
|
+
arguments.summary_indent = " "
|
31
|
+
arguments.summary_width = 24
|
32
|
+
arguments.banner = <<-end_banner.gsub /^[ ]{4}/, ''
|
33
|
+
#{Prigner::Version}
|
34
|
+
|
35
|
+
List all templates.
|
36
|
+
|
37
|
+
Usage:
|
38
|
+
#{program} #{command}
|
39
|
+
|
40
|
+
end_banner
|
41
|
+
|
42
|
+
if ARGV.empty?
|
43
|
+
show(templates_by_namespace(arguments.summary_indent))
|
44
|
+
exit 0
|
45
|
+
else
|
46
|
+
arguments.parse!
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
rescue => error
|
51
|
+
puts "#{program}: #{command}: #{error.message} (#{error.class})"
|
52
|
+
exit 1
|
53
|
+
end
|
54
|
+
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Copyright (c) 2010 Hallison Batista
|
2
|
+
|
3
|
+
require "prigner"
|
4
|
+
|
5
|
+
program = :prign
|
6
|
+
command = File.basename(__FILE__, ".rb")
|
7
|
+
|
8
|
+
begin
|
9
|
+
ARGV.options do |arguments|
|
10
|
+
|
11
|
+
arguments.summary_indent = " "
|
12
|
+
arguments.summary_width = 24
|
13
|
+
arguments.banner = <<-end_banner.gsub /^[ ]{6}/, ''
|
14
|
+
#{Prigner::Version}
|
15
|
+
|
16
|
+
Usage:
|
17
|
+
#{program} #{command} <namespace>[:template] <path> [options]
|
18
|
+
|
19
|
+
Templates:
|
20
|
+
#{Prigner::CLI.templates.sort.join("\n" + arguments.summary_indent)}
|
21
|
+
|
22
|
+
end_banner
|
23
|
+
|
24
|
+
unless ARGV.empty?
|
25
|
+
name = ARGV.shift
|
26
|
+
path = ARGV.shift unless name.nil?
|
27
|
+
|
28
|
+
template = Prigner::Template.load(*name.split(":"))
|
29
|
+
|
30
|
+
if template
|
31
|
+
arguments.banner = <<-end_banner.gsub /^[ ]{10}/, ''
|
32
|
+
#{Prigner::Version}
|
33
|
+
|
34
|
+
Usage:
|
35
|
+
#{program} #{command} #{template.mask} <path> [options]
|
36
|
+
|
37
|
+
end_banner
|
38
|
+
|
39
|
+
if template.options
|
40
|
+
arguments.separator "Options:"
|
41
|
+
|
42
|
+
template.options.members.map do |name|
|
43
|
+
option = template.options[name]
|
44
|
+
arguments.on("-#{name[0..0]}", "--#{name}", nil, option.description) do
|
45
|
+
option.enabled = true
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
else
|
51
|
+
raise RuntimeError, "unable to load template '#{name}'"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
unless path
|
56
|
+
puts arguments
|
57
|
+
exit 0
|
58
|
+
end
|
59
|
+
|
60
|
+
arguments.parse!
|
61
|
+
|
62
|
+
project = Prigner::Project.new(path)
|
63
|
+
builder = Prigner::Builder.new(project, template)
|
64
|
+
|
65
|
+
status = Prigner::CLI::Status.new
|
66
|
+
|
67
|
+
status.setup do
|
68
|
+
state :success, :created
|
69
|
+
state :failure, :fail
|
70
|
+
state :error, :error
|
71
|
+
format :title, "\n* %-74s"
|
72
|
+
format :info, " %-69s [%7s]"
|
73
|
+
end
|
74
|
+
|
75
|
+
puts Prigner::Version
|
76
|
+
|
77
|
+
status.start "Creating project path" do
|
78
|
+
builder.make_project_path
|
79
|
+
end
|
80
|
+
|
81
|
+
status.start "Creating directories" do
|
82
|
+
builder.make_project_directories
|
83
|
+
end
|
84
|
+
|
85
|
+
status.start "Writing files" do
|
86
|
+
builder.make_project_files
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
|
91
|
+
rescue => error
|
92
|
+
puts "#{program}: #{command}: #{error.message} (#{error.class})"
|
93
|
+
puts "Try '#{program} #{command} -h' or '#{program} #{command} --help' for more information."
|
94
|
+
exit 1
|
95
|
+
end
|
96
|
+
|
data/lib/prigner/cli.rb
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
# == Command-Line Interface
|
2
|
+
#
|
3
|
+
# This module look a command placed in CLI directory and run it.
|
4
|
+
module Prigner::CLI
|
5
|
+
|
6
|
+
require "rbconfig"
|
7
|
+
|
8
|
+
# Ruby VM installed in OS.
|
9
|
+
def self.ruby
|
10
|
+
File.join(*::RbConfig::CONFIG.values_at("bindir", "ruby_install_name")) +
|
11
|
+
::RbConfig::CONFIG["EXEEXT"]
|
12
|
+
end
|
13
|
+
|
14
|
+
# The CLI path.
|
15
|
+
def self.path
|
16
|
+
"#{Prigner::ROOT}/lib/prigner/cli"
|
17
|
+
end
|
18
|
+
|
19
|
+
# List all templates as commands.
|
20
|
+
def self.templates
|
21
|
+
Prigner::Template.all.map do |namespace, templates|
|
22
|
+
templates.map{ |template| template.mask }
|
23
|
+
end.flatten
|
24
|
+
end
|
25
|
+
|
26
|
+
# List of commands placed in <tt>lib/prigner/cli/</tt>.
|
27
|
+
def self.commands
|
28
|
+
Dir["#{path}/*.rb"].map do |source|
|
29
|
+
File.basename(source, ".rb")
|
30
|
+
end.sort
|
31
|
+
end
|
32
|
+
|
33
|
+
# Source command placed in CLI directory.
|
34
|
+
def self.source(command)
|
35
|
+
"#{path}/#{command}.rb"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Look command in *CLI* directory and execute (by exec).
|
39
|
+
def self.run(*args)
|
40
|
+
command = args.shift if commands.include? args.first
|
41
|
+
raise RuntimeError, "unknown command '#{args.first}'" unless command
|
42
|
+
rubyopt = "-I#{Prigner::ROOT}/lib"
|
43
|
+
exec ruby, rubyopt, source(command), *args
|
44
|
+
end
|
45
|
+
|
46
|
+
class Status
|
47
|
+
|
48
|
+
attr_reader :formats
|
49
|
+
|
50
|
+
attr_reader :count
|
51
|
+
|
52
|
+
attr_reader :states
|
53
|
+
|
54
|
+
attr_reader :current
|
55
|
+
|
56
|
+
def initialize
|
57
|
+
@states = {
|
58
|
+
:success => :done,
|
59
|
+
:failure => :fail,
|
60
|
+
:error => :err
|
61
|
+
}
|
62
|
+
@formats = {
|
63
|
+
:title => "\n* %-74s",
|
64
|
+
:info => "\n %-70s [%4s]"
|
65
|
+
}
|
66
|
+
@count = {}
|
67
|
+
@states.keys.each{|k| @count[k] = 0 }
|
68
|
+
end
|
69
|
+
|
70
|
+
def setup(&block)
|
71
|
+
instance_eval(&block)
|
72
|
+
end
|
73
|
+
|
74
|
+
def state(key, value)
|
75
|
+
return unless @states.has_key?key
|
76
|
+
@states[key] = value
|
77
|
+
@count[key] = 0
|
78
|
+
end
|
79
|
+
|
80
|
+
def format(key, format)
|
81
|
+
@formats[key] = "#{format}\n" if @formats.has_key?key
|
82
|
+
end
|
83
|
+
|
84
|
+
def increment!
|
85
|
+
@count[@current] += 1
|
86
|
+
end
|
87
|
+
|
88
|
+
def start(title, &block)
|
89
|
+
printf @formats[:title], title
|
90
|
+
hash = yield block
|
91
|
+
hash.each do |message, status|
|
92
|
+
@current = status ? :success : :failure
|
93
|
+
printf @formats[:info], message, @states[@current]
|
94
|
+
increment!
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class Symbol
|
2
|
+
|
3
|
+
# Method for comparison between symbols.
|
4
|
+
def <=>(other)
|
5
|
+
self.to_s <=> other.to_s
|
6
|
+
end
|
7
|
+
|
8
|
+
end
|
9
|
+
|
10
|
+
class Hash
|
11
|
+
|
12
|
+
alias has? has_key?
|
13
|
+
|
14
|
+
# Only symbolize all keys, including all key in sub-hashes.
|
15
|
+
def symbolize_keys
|
16
|
+
return self.clone if self.empty?
|
17
|
+
self.inject({}) do |hash, (key, value)|
|
18
|
+
hash[key.to_sym] = if value.kind_of? Hash
|
19
|
+
value.symbolize_keys
|
20
|
+
else
|
21
|
+
value
|
22
|
+
end
|
23
|
+
hash
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Set instance variables by key and value only if object respond
|
28
|
+
# to access method for variable.
|
29
|
+
def instance_variables_set_to(object)
|
30
|
+
collect do |variable, value|
|
31
|
+
object.instance_variable_set("@#{variable}", value) if object.respond_to? variable
|
32
|
+
end
|
33
|
+
object
|
34
|
+
end
|
35
|
+
|
36
|
+
# Convert to Struct including all values that are Hash class.
|
37
|
+
def to_struct
|
38
|
+
keys = self.keys.sort
|
39
|
+
members = keys.map{ |key| key.to_sym }
|
40
|
+
Struct.new(*members).new(*keys.map do |key|
|
41
|
+
if self[key].kind_of? Hash
|
42
|
+
self[key].to_struct
|
43
|
+
else
|
44
|
+
self[key]
|
45
|
+
end
|
46
|
+
end) unless self.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
class Struct
|
52
|
+
|
53
|
+
# Public bind.
|
54
|
+
def binding
|
55
|
+
super
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
class Pathname
|
61
|
+
|
62
|
+
def chpath(source, path)
|
63
|
+
self.path.gsub(%r{#{source}}, path).to_path
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# == Model
|
2
|
+
#
|
3
|
+
# This class implements several methods for load a model file of template.
|
4
|
+
#
|
5
|
+
# Basically behaviour as parser based in a ERB file placed in +models+
|
6
|
+
# directory of a Template.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# # model: jedi/knight
|
11
|
+
# class <%=name.capitalize%>
|
12
|
+
# <%for attribute in attributes%>
|
13
|
+
# attr_accessor :<%=attribute%>
|
14
|
+
# <%end%>
|
15
|
+
# def initialize(<%=attributes.join(",")%>)
|
16
|
+
# <%for attribute in attributes%>
|
17
|
+
# @<%=attribute%> = <%attribute%>
|
18
|
+
# <%end%>
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# def to_s
|
22
|
+
# <%for attribute in attributes%>
|
23
|
+
# "\n<%=attribute.capitalize%>: #{<%=attribute%>}"
|
24
|
+
# <%end%>
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# <%=name%> = <%=name.capitalize%>.new("Yoda", "Jedi Grand Master")
|
29
|
+
# # end model
|
30
|
+
#
|
31
|
+
# $> model = Pringer::Model.new "jedi/knight", {
|
32
|
+
# :name => "knight",
|
33
|
+
# :attributes => [ :name, :position ]
|
34
|
+
# }
|
35
|
+
# $> model.build!
|
36
|
+
# $> model.contents
|
37
|
+
# => class Knight
|
38
|
+
# =>
|
39
|
+
# => attr_accessor :name
|
40
|
+
# => attr_accessor :position
|
41
|
+
# =>
|
42
|
+
# => def initialize(name,position)
|
43
|
+
# =>
|
44
|
+
# => @name = name
|
45
|
+
# => @position = position
|
46
|
+
# =>
|
47
|
+
# => end
|
48
|
+
# =>
|
49
|
+
# => def to_s
|
50
|
+
# =>
|
51
|
+
# => "\nName: #{name}"
|
52
|
+
# => "\nPosition: #{position}"
|
53
|
+
# =>
|
54
|
+
# => end
|
55
|
+
# => end
|
56
|
+
# =>
|
57
|
+
# => knight = Knight.new("Yoda", "Jedi Grand Master")
|
58
|
+
#
|
59
|
+
class Prigner::Model
|
60
|
+
|
61
|
+
# Model path file.
|
62
|
+
attr_reader :path
|
63
|
+
|
64
|
+
# Parsed contents.
|
65
|
+
attr_reader :contents
|
66
|
+
|
67
|
+
# Value bindings.
|
68
|
+
attr_accessor :binder
|
69
|
+
|
70
|
+
# Result file written
|
71
|
+
attr_reader :file_written
|
72
|
+
|
73
|
+
# Initializes a model passing all attributes by Hash.
|
74
|
+
def initialize(path, binder = {})
|
75
|
+
@path = Pathname.new(path)
|
76
|
+
@binder = (binder.kind_of? Hash) ? binder.to_struct : binder
|
77
|
+
end
|
78
|
+
|
79
|
+
# Build model contents.
|
80
|
+
def build!
|
81
|
+
require "erb"
|
82
|
+
@contents = ::ERB.new(@path.read).result(binder.binding)
|
83
|
+
end
|
84
|
+
|
85
|
+
# Write contents into file.
|
86
|
+
def write(file)
|
87
|
+
@file_written = file
|
88
|
+
file = Pathname.new(file)
|
89
|
+
file.dirname.mkpath
|
90
|
+
file.open "w+" do |output|
|
91
|
+
output << self.build!
|
92
|
+
end
|
93
|
+
self
|
94
|
+
end
|
95
|
+
|
96
|
+
end
|
97
|
+
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# == Project
|
2
|
+
#
|
3
|
+
# This class is a simple implementation of a tree of directories. It is used
|
4
|
+
# in model files.
|
5
|
+
class Prigner::Project
|
6
|
+
|
7
|
+
# Project name.
|
8
|
+
attr_reader :name
|
9
|
+
|
10
|
+
alias project name
|
11
|
+
|
12
|
+
# Project files.
|
13
|
+
attr_reader :path
|
14
|
+
|
15
|
+
# Project timestamp
|
16
|
+
attr_reader :timestamp
|
17
|
+
|
18
|
+
# Initialize a new project directory path.
|
19
|
+
def initialize(path)
|
20
|
+
@path = File.expand_path(path =~ /^\/.*/ ? path : "#{Dir.pwd}/#{path}")
|
21
|
+
@name = File.basename(@path)
|
22
|
+
@timestamp = DateTime.now
|
23
|
+
end
|
24
|
+
|
25
|
+
def name_splited
|
26
|
+
@name.split(/[-_]/)
|
27
|
+
end
|
28
|
+
|
29
|
+
def namespace(joiner = "::")
|
30
|
+
name_splited.join(joiner)
|
31
|
+
end
|
32
|
+
|
33
|
+
def upper_camel_case_namespace(joiner = "::")
|
34
|
+
name_splited.map{ |str| str.capitalize }.join(joiner)
|
35
|
+
end
|
36
|
+
|
37
|
+
def lower_camel_case_namespace(joiner = "::")
|
38
|
+
return name if name_splited.size == 0
|
39
|
+
name_splited[1..-1].map do |str|
|
40
|
+
str.capitalize
|
41
|
+
end.unshift(name_splited.first).join(joiner)
|
42
|
+
end
|
43
|
+
|
44
|
+
def upper_case_namespace(joiner = "::")
|
45
|
+
upper_camel_case_namespace(joiner).upcase
|
46
|
+
end
|
47
|
+
|
48
|
+
def lower_case_namespace(joiner = "::")
|
49
|
+
upper_camel_case_namespace(joiner).downcase
|
50
|
+
end
|
51
|
+
|
52
|
+
def upper_camel_case_name
|
53
|
+
upper_camel_case_namespace(nil)
|
54
|
+
end
|
55
|
+
|
56
|
+
alias class_name upper_camel_case_name
|
57
|
+
|
58
|
+
def lower_camel_case_name
|
59
|
+
lower_camel_case_namespace(nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
def user
|
63
|
+
Etc.getpwnam(Etc.getlogin)
|
64
|
+
end
|
65
|
+
|
66
|
+
def author
|
67
|
+
self.user.gecos.split(",").first
|
68
|
+
end
|
69
|
+
|
70
|
+
end # Project
|
71
|
+
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# == Project Template
|
2
|
+
#
|
3
|
+
# This class implements several methods for load a template for a new project.
|
4
|
+
# Basically, a template is based in an YAML file for +specfile+ and a directory
|
5
|
+
# containing all files to be parsed.
|
6
|
+
#
|
7
|
+
# The template tree is based in following structure:
|
8
|
+
#
|
9
|
+
# namespace
|
10
|
+
# `-- template
|
11
|
+
# |-- models
|
12
|
+
# `-- specfile
|
13
|
+
#
|
14
|
+
# See Spec class for more information about mandatory attributes for draw your
|
15
|
+
# project using +specfile+.
|
16
|
+
class Prigner::Template
|
17
|
+
|
18
|
+
# Namespace of template.
|
19
|
+
attr_reader :namespace
|
20
|
+
|
21
|
+
# Name of template.
|
22
|
+
attr_reader :name
|
23
|
+
|
24
|
+
# List of models.
|
25
|
+
attr_reader :models
|
26
|
+
|
27
|
+
# List of directories that will created in project tree.
|
28
|
+
attr_reader :directories
|
29
|
+
|
30
|
+
# List of options (see Spec#options).
|
31
|
+
attr_reader :options
|
32
|
+
|
33
|
+
# Path to template.
|
34
|
+
attr_reader :path
|
35
|
+
|
36
|
+
# Specifications
|
37
|
+
attr_reader :spec
|
38
|
+
|
39
|
+
# Initialize a template using a path.
|
40
|
+
#
|
41
|
+
# Example:
|
42
|
+
#
|
43
|
+
# template = Prigner::Template.new "path/to/template"
|
44
|
+
#
|
45
|
+
# The template initialization will search the +specfile+ in path passed as
|
46
|
+
# argument (<tt>path/to/template/specfile</tt>) for Spec attributes.
|
47
|
+
def initialize(path)
|
48
|
+
@path = Pathname.new(path).tap{ |check| check.stat }
|
49
|
+
@namespace = @path.parent.basename.to_s
|
50
|
+
@name = @path.basename.to_s
|
51
|
+
initialize_specfile
|
52
|
+
initialize_options
|
53
|
+
initialize_directories
|
54
|
+
initialize_models
|
55
|
+
rescue Exception => error
|
56
|
+
raise RuntimeError, error.message
|
57
|
+
end
|
58
|
+
|
59
|
+
# Mask for presentation of template.
|
60
|
+
def mask
|
61
|
+
@name == "default" ? @namespace : "#{@namespace}:#{@name}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Load template from shared directories. The shared path set the home user
|
65
|
+
# directory and Prigner::Template shared files.
|
66
|
+
def self.load(namespace, template = :default)
|
67
|
+
shared_path.map do |source|
|
68
|
+
path = "#{source}/#{namespace}/#{template}"
|
69
|
+
return new(path) if File.exist? path
|
70
|
+
end
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
|
74
|
+
# Look at user home and template shared path.
|
75
|
+
def self.shared_path
|
76
|
+
user_home_templates = File.join(user_home_basedir, "templates")
|
77
|
+
[ user_home_templates, "#{Prigner::ROOT}/share/templates" ]
|
78
|
+
end
|
79
|
+
|
80
|
+
# User home.
|
81
|
+
def self.user_home
|
82
|
+
File.expand_path "~"
|
83
|
+
rescue
|
84
|
+
if File::ALT_SEPARATOR then
|
85
|
+
"C:/"
|
86
|
+
else
|
87
|
+
"/"
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# User home base directory for Prigner files.
|
92
|
+
def self.user_home_basedir
|
93
|
+
File.join(user_home, ".prigner")
|
94
|
+
end
|
95
|
+
|
96
|
+
# Return all template paths placed in shared user or in project base
|
97
|
+
# directory.
|
98
|
+
def self.all_template_paths
|
99
|
+
shared_path.map do |source|
|
100
|
+
Dir.glob("#{source}/*/*")
|
101
|
+
end.flatten.compact
|
102
|
+
end
|
103
|
+
|
104
|
+
# All templates grouped by namespace.
|
105
|
+
def self.all
|
106
|
+
all_template_paths.map do |path|
|
107
|
+
new(path)
|
108
|
+
end.inject({}) do |group, template|
|
109
|
+
group[template.namespace] ||= []
|
110
|
+
group[template.namespace] << template
|
111
|
+
group
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
# Return the specfile placed in template path.
|
118
|
+
def specfile
|
119
|
+
Dir["#{@path}/[Ss]pecfile"].first
|
120
|
+
end
|
121
|
+
|
122
|
+
# Load +specfile+ placed in template path.
|
123
|
+
def initialize_specfile
|
124
|
+
@spec = Prigner::Spec.load(specfile)
|
125
|
+
end
|
126
|
+
|
127
|
+
# Initialize options.
|
128
|
+
def initialize_options
|
129
|
+
@options = @spec.options.inject({}) do |options, (name, desc)|
|
130
|
+
options[name] = { :enabled => nil, :description => desc }
|
131
|
+
options
|
132
|
+
end.to_struct if @spec.options
|
133
|
+
end
|
134
|
+
|
135
|
+
def initialize_directories
|
136
|
+
@directories = @spec.directories
|
137
|
+
end
|
138
|
+
|
139
|
+
def initialize_models
|
140
|
+
@models = @spec.files.inject({}) do |models, (source, file)|
|
141
|
+
model = Prigner::Model.new(@path.join("models", source))
|
142
|
+
models[model] = file ? file : source
|
143
|
+
models
|
144
|
+
end if @spec.files
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
|