skeletor 0.6.3 → 0.6.4
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +139 -0
- data/lib/skeletor.rb +1 -0
- data/lib/skeletor/builder.rb +18 -0
- data/lib/skeletor/cli.rb +7 -1
- data/lib/skeletor/includes.rb +6 -0
- data/lib/skeletor/protocols/http.rb +1 -0
- data/lib/skeletor/protocols/https.rb +1 -1
- data/lib/skeletor/skeletons.rb +1 -0
- data/lib/skeletor/skeletons/loader.rb +10 -2
- data/lib/skeletor/skeletons/skeleton.rb +8 -0
- data/lib/skeletor/skeletons/validator.rb +17 -2
- data/lib/skeletor/tasks.rb +4 -0
- data/lib/skeletor/version.rb +2 -1
- metadata +3 -3
data/README.md
CHANGED
@@ -43,6 +43,145 @@ Validates that TEMPLATE is a valid YAML file and that it matches the expected sc
|
|
43
43
|
|
44
44
|
Shows help information for TASK.
|
45
45
|
|
46
|
+
Templates
|
47
|
+
---------
|
48
|
+
|
49
|
+
###Creating Templates###
|
50
|
+
|
51
|
+
A Skeletor template is a YAML file in a folder with the same name as the file so for instance, a basic template on file would look like this:
|
52
|
+
|
53
|
+
sample-template/
|
54
|
+
- sample-template.yml
|
55
|
+
|
56
|
+
The yaml structure looks like this:
|
57
|
+
|
58
|
+
directory_structure:
|
59
|
+
-
|
60
|
+
dirname:
|
61
|
+
-
|
62
|
+
subdir:
|
63
|
+
-
|
64
|
+
NESTEDFILE
|
65
|
+
-
|
66
|
+
FILENAME
|
67
|
+
includes:
|
68
|
+
FILENAME: path/to/file
|
69
|
+
NESTEDFILE: remoteurloffile
|
70
|
+
tasks:
|
71
|
+
- TASKANDARGUMENTS
|
72
|
+
- ANOTHERTASKANDARGUMENTS
|
73
|
+
|
74
|
+
It should match the following schema:
|
75
|
+
|
76
|
+
sections:
|
77
|
+
- name: directory_structure
|
78
|
+
required: yes
|
79
|
+
type: Array
|
80
|
+
ok_empty: yes
|
81
|
+
accepts:
|
82
|
+
- directory_list
|
83
|
+
- file_list
|
84
|
+
- name: tasks
|
85
|
+
required: no
|
86
|
+
type: Array
|
87
|
+
accepts:
|
88
|
+
- String
|
89
|
+
- name: includes
|
90
|
+
required: no
|
91
|
+
type: Hash
|
92
|
+
accepts:
|
93
|
+
- String
|
94
|
+
types:
|
95
|
+
directory_list:
|
96
|
+
type: Hash
|
97
|
+
ok_empty: no
|
98
|
+
accepts:
|
99
|
+
- directory
|
100
|
+
file_list:
|
101
|
+
type: Array
|
102
|
+
ok_empty: no
|
103
|
+
accepts:
|
104
|
+
- file
|
105
|
+
directory:
|
106
|
+
type: Array
|
107
|
+
ok_empty: yes
|
108
|
+
accepts:
|
109
|
+
- empty
|
110
|
+
- directory_list
|
111
|
+
- file_list
|
112
|
+
file:
|
113
|
+
type: String
|
114
|
+
|
115
|
+
|
116
|
+
It contains 3 optional sections:
|
117
|
+
|
118
|
+
####directory_structure####
|
119
|
+
|
120
|
+
This is the main part of the template, but you can still leave it out if you just want skeletor to run tasks for you. In YAML parlance the directory_structure is a sequence
|
121
|
+
that contains either sequences or mappings. What this basically means is that it can contain a list of directories and a list of files. The directory lists are mappings as
|
122
|
+
well, with the directory name being the mapping name and the contents being another sequence defining a list of directories and/or a list of files. The file list is a sequence
|
123
|
+
of strings that define the file names. If the filenames are not listed in the includes section blank files will be created, otherwise the include will be copied from the given location.
|
124
|
+
To specify an empty directory just create an empty mapping but remember to still put a space after the colon as YAML seems to be funny about parsing without that. You can use the built in
|
125
|
+
validate action to check your template and the build action will also validate the template on load.
|
126
|
+
|
127
|
+
####includes####
|
128
|
+
|
129
|
+
This is a mapping of filenames to include locations. The include locations can be anywhere on disk or a remote location accessible through either HTTP or HTTPS. Generally I would recommend
|
130
|
+
storing these in subfolders in your template directory.
|
131
|
+
|
132
|
+
####tasks####
|
133
|
+
|
134
|
+
This denotes a list of tasks to run once the skeleton is set up. They are a string in the following format:
|
135
|
+
|
136
|
+
task[, argument...]
|
137
|
+
|
138
|
+
So for example to call the built in git_init task the tasks section would look like this
|
139
|
+
|
140
|
+
tasks:
|
141
|
+
- git_init, <skeleton_path>
|
142
|
+
|
143
|
+
You can pass any arguments you want but there are 3 placeholders that can be used to populate with data from the skeleton:
|
144
|
+
|
145
|
+
* `<skeleton_path>` passes the location of the created skeleton to the task
|
146
|
+
* `<skeleton_project>` passes the project name to the task
|
147
|
+
* `<skeleton_template>` passes the name of the template used to the task
|
148
|
+
|
149
|
+
There are also 2 built in tasks:
|
150
|
+
|
151
|
+
* `git_init` Initializes a git repository in the newly created project
|
152
|
+
* `capify` Generates capistrano deployment files
|
153
|
+
|
154
|
+
The parser will look for built in tasks with the names supplied first so if you want to provide your own versions you will need to change the names. To supply your own tasks
|
155
|
+
put them in a `tasks.rb` file in the root of your template directory.
|
156
|
+
|
157
|
+
###Storing Templates###
|
158
|
+
|
159
|
+
You can store the templates anywhere you like and just pass the path to them to the function but for ease of use you can create a `.skeletor` folder in your home directory and
|
160
|
+
put your templates in a `templates` folder under that. This way you just have to pass the template name and Skeletor will look here for the template.
|
161
|
+
|
162
|
+
###Supplied Templates###
|
163
|
+
|
164
|
+
Skeletor comes with 1 presupplied template but I'll be adding a few more as I have time.
|
165
|
+
|
166
|
+
* `js-lib` Creates a skeleton for a Javascript library. This is based on the structure I use for most Javascript projects which is in turn based on the structures of libraries such
|
167
|
+
as Prototype and Scriptaculous.
|
168
|
+
|
169
|
+
Coming Soon
|
170
|
+
-----------
|
171
|
+
|
172
|
+
* Add rDoc comments so rubygems.org can generate proper documentation
|
173
|
+
* Add Tests
|
174
|
+
* More Templates
|
175
|
+
* Option to turn off or lessen output
|
176
|
+
* Include parsing
|
177
|
+
* Option to deal with file/folder existing conflicts.
|
178
|
+
|
179
|
+
Notes
|
180
|
+
-----
|
181
|
+
|
182
|
+
This is my first gem and my first major work with ruby, so I'd be really grateful for any constructive feedback, input, suggestions etc. Also if anybody wants to
|
183
|
+
contribute feel free, just check out the guidelines below (pretty standard stuff but it kinda makes sense).
|
184
|
+
|
46
185
|
Contributing to Skeletor
|
47
186
|
------------------------
|
48
187
|
|
data/lib/skeletor.rb
CHANGED
data/lib/skeletor/builder.rb
CHANGED
@@ -2,8 +2,11 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
module Skeletor
|
4
4
|
|
5
|
+
# The *Builder* class performs the main task of parsing the
|
6
|
+
# loaded *Skeleton* and generating a project structure from it.
|
5
7
|
class Builder
|
6
8
|
|
9
|
+
# Creates a new *Builder* instance
|
7
10
|
def initialize(project,template,path)
|
8
11
|
|
9
12
|
@project = project
|
@@ -13,6 +16,13 @@ module Skeletor
|
|
13
16
|
|
14
17
|
end
|
15
18
|
|
19
|
+
# Builds the project skeleton
|
20
|
+
#
|
21
|
+
# If the target directory does not exist it is created, then the
|
22
|
+
# directory structure is generated.
|
23
|
+
#
|
24
|
+
# Once the folder structure is set up and all includes have been
|
25
|
+
# loaded/created, any tasks specified in the template file are run.
|
16
26
|
def build()
|
17
27
|
|
18
28
|
#check dir exists, if not, make it
|
@@ -32,6 +42,7 @@ module Skeletor
|
|
32
42
|
|
33
43
|
end
|
34
44
|
|
45
|
+
# Builds the directory structure
|
35
46
|
def build_skeleton(dirs,path=@path)
|
36
47
|
|
37
48
|
dirs.each{
|
@@ -62,6 +73,7 @@ module Skeletor
|
|
62
73
|
|
63
74
|
end
|
64
75
|
|
76
|
+
# Cleans the directory of all files and folders
|
65
77
|
def self.clean(path=@path)
|
66
78
|
|
67
79
|
puts 'Cleaning directory of files and folders'
|
@@ -79,6 +91,8 @@ module Skeletor
|
|
79
91
|
|
80
92
|
end
|
81
93
|
|
94
|
+
# Checks if file is listed in the includes list and if so copies it from
|
95
|
+
# the given location. If not it creates a blank file.
|
82
96
|
def write_file(file,path)
|
83
97
|
|
84
98
|
#if a pre-existing file is specified in the includes list, copy that, if not write a blank file
|
@@ -96,6 +110,10 @@ module Skeletor
|
|
96
110
|
|
97
111
|
end
|
98
112
|
|
113
|
+
# Parses the task string and runs the task.
|
114
|
+
#
|
115
|
+
# Will check *Skeleton::Tasks* module first before running tasks
|
116
|
+
# from the `tasks.rb` file in the template directory.
|
99
117
|
def execute_tasks(tasks,template_path)
|
100
118
|
|
101
119
|
if File.exists?(File.expand_path(File.join(template_path,'tasks.rb')))
|
data/lib/skeletor/cli.rb
CHANGED
@@ -2,8 +2,10 @@ require 'thor'
|
|
2
2
|
|
3
3
|
module Skeletor
|
4
4
|
|
5
|
+
# The *CLI* class provides an interface for the command line functions
|
5
6
|
class CLI < Thor
|
6
7
|
|
8
|
+
|
7
9
|
desc "build TEMPLATE [options]", "Build project skeleton from TEMPLATE"
|
8
10
|
method_option :directory,
|
9
11
|
:aliases => "-d",
|
@@ -11,6 +13,7 @@ module Skeletor
|
|
11
13
|
method_option :project,
|
12
14
|
:aliases => "-p",
|
13
15
|
:desc => "Sets the project name. Defaults to current directory name."
|
16
|
+
# Creates a new *Builder* instance and builds the skeleton in the specified directory
|
14
17
|
def build(template)
|
15
18
|
path = options[:directory] || Dir.pwd
|
16
19
|
project = options[:project] || File.basename(path)
|
@@ -19,10 +22,12 @@ module Skeletor
|
|
19
22
|
skeleton.build
|
20
23
|
end
|
21
24
|
|
25
|
+
|
22
26
|
desc "clean [options]" ,"Clean directory"
|
23
27
|
method_option :directory,
|
24
28
|
:aliases => "-d",
|
25
29
|
:desc => "Sets the target directory. Defaults to current directory"
|
30
|
+
# Cleans out the specified directory
|
26
31
|
def clean
|
27
32
|
print 'Are you sure you want to clean this project directory? (Y|n): '
|
28
33
|
confirm = gets.chomp
|
@@ -35,7 +40,8 @@ module Skeletor
|
|
35
40
|
|
36
41
|
end
|
37
42
|
|
38
|
-
desc "validate TEMPLATE" ,"Checks TEMPLATE is a valid YAML file and matches the required schema."
|
43
|
+
desc "validate TEMPLATE" ,"Checks TEMPLATE is a valid YAML file and matches the required schema."
|
44
|
+
# Loads a template, creates a new *Validator* and validates the template
|
39
45
|
def validate(template)
|
40
46
|
skeleton = Skeletons::Loader.loadTemplate(template)
|
41
47
|
validator = Skeletons::Validator.new(skeleton)
|
data/lib/skeletor/includes.rb
CHANGED
@@ -5,11 +5,17 @@ autoload :HTTPS, 'skeletor/protocols/https'
|
|
5
5
|
|
6
6
|
module Skeletor
|
7
7
|
|
8
|
+
# The *Includes* class contains methods for dealing with
|
9
|
+
# loading and parsing required include files.
|
8
10
|
class Includes
|
9
11
|
|
12
|
+
# Internal regular expression to match for includes that should be loaded from a remote destination
|
10
13
|
PROTOCOL_PATTERN = /(?:([a-z][\w-]+):(?:\/{1,3}|[a-z0-9%]))/
|
14
|
+
# Specifies a list of supported protocols that *Skeletor* can load from.
|
11
15
|
SUPPORTED_PROTOCOLS = ['http','https']
|
12
16
|
|
17
|
+
# Reads the required include from either the remote url or the local path and writes it to the
|
18
|
+
# required location in the skeleton.
|
13
19
|
def self.copy_include(include,target,path)
|
14
20
|
|
15
21
|
#if include path includes a protocol. Load from that
|
data/lib/skeletor/skeletons.rb
CHANGED
@@ -3,12 +3,20 @@ require 'YAML'
|
|
3
3
|
module Skeletor
|
4
4
|
|
5
5
|
module Skeletons
|
6
|
-
|
6
|
+
# *Loader* is a wrapper class to handle loading in the template file
|
7
|
+
# from the various possible load paths.
|
8
|
+
#
|
9
|
+
# While accessible externally this is generally called internally.
|
7
10
|
class Loader
|
8
11
|
|
12
|
+
# *TEMPLATE_PATH* specifies the internal directory for any included project templates.
|
9
13
|
TEMPLATE_PATH = File.expand_path(File.join(File.dirname(File.dirname(__FILE__)), "templates"))
|
14
|
+
# *USER_TEMPLATE_PATH* specifies the path to the users personal template directory
|
10
15
|
USER_TEMPLATE_PATH = File.expand_path('~/.skeletor/templates')
|
11
|
-
|
16
|
+
|
17
|
+
# Searches for the specified template and loads it into a variable
|
18
|
+
#
|
19
|
+
# Also adds the path where it was found to the returned Hash
|
12
20
|
def self.loadTemplate(template)
|
13
21
|
|
14
22
|
puts 'Loading Template - ' + template
|
@@ -2,8 +2,12 @@ module Skeletor
|
|
2
2
|
|
3
3
|
module Skeletons
|
4
4
|
|
5
|
+
# The *Skeleton* class provides a wrapper round the template file
|
6
|
+
# and handles loading it and validating it, as well as providing
|
7
|
+
# default values for any missing sections.
|
5
8
|
class Skeleton
|
6
9
|
|
10
|
+
#Creates a new *Skeleton* instance from `template`
|
7
11
|
def initialize(template)
|
8
12
|
|
9
13
|
begin
|
@@ -24,18 +28,22 @@ module Skeletor
|
|
24
28
|
|
25
29
|
end
|
26
30
|
|
31
|
+
# Returns the directory structure section
|
27
32
|
def directory_structure
|
28
33
|
@directory_structure
|
29
34
|
end
|
30
35
|
|
36
|
+
# Returns the tasks section
|
31
37
|
def tasks
|
32
38
|
@tasks
|
33
39
|
end
|
34
40
|
|
41
|
+
# Returns the includes section
|
35
42
|
def includes
|
36
43
|
@includes
|
37
44
|
end
|
38
45
|
|
46
|
+
# Returns the template path
|
39
47
|
def path
|
40
48
|
@path
|
41
49
|
end
|
@@ -2,10 +2,15 @@ module Skeletor
|
|
2
2
|
|
3
3
|
module Skeletons
|
4
4
|
|
5
|
+
# *Validator* handles validation of the loaded project template files against
|
6
|
+
# the required schema
|
7
|
+
|
5
8
|
class Validator
|
6
9
|
|
10
|
+
# Defines the location to the required schema file for the templates
|
7
11
|
SCHEMA_FILE = File.join Skeletons::Loader::TEMPLATE_PATH,'template-schema.yml'
|
8
12
|
|
13
|
+
# Creates a new *Validator* instance
|
9
14
|
def initialize(template,schema=SCHEMA_FILE)
|
10
15
|
@errors = []
|
11
16
|
@template = template
|
@@ -13,7 +18,8 @@ module Skeletor
|
|
13
18
|
@types = @schema['types'] || {}
|
14
19
|
end
|
15
20
|
|
16
|
-
|
21
|
+
# Validates the template against the schema
|
22
|
+
def validate()
|
17
23
|
failed = []
|
18
24
|
|
19
25
|
@schema['sections'].each{
|
@@ -48,7 +54,11 @@ module Skeletor
|
|
48
54
|
end
|
49
55
|
|
50
56
|
end
|
51
|
-
|
57
|
+
|
58
|
+
# Checks template node matches the schema.
|
59
|
+
#
|
60
|
+
# Checks type of node against expected type and
|
61
|
+
# checks any children are of the accepted types.
|
52
62
|
def match_node(node,expected,label)
|
53
63
|
|
54
64
|
#check type
|
@@ -149,6 +159,11 @@ module Skeletor
|
|
149
159
|
|
150
160
|
end
|
151
161
|
|
162
|
+
# Checks that the node is of the correct type
|
163
|
+
#
|
164
|
+
# If the expected node is a custom node type as defined in the schema
|
165
|
+
# It will run `match_node` to check that the node schema matches the
|
166
|
+
# custom type.
|
152
167
|
def check_type(node,expected_type,label,accept_nil = false)
|
153
168
|
|
154
169
|
valid_type = true;
|
data/lib/skeletor/tasks.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
module Skeletor
|
2
2
|
|
3
|
+
# The *Tasks* class contains the included tasks that may
|
4
|
+
# be run after the skeleton has been created.
|
3
5
|
class Tasks
|
4
6
|
|
7
|
+
# Initializes an empty git repository in the new project directory
|
5
8
|
def self.git_init(path)
|
6
9
|
system "cd " + path + '
|
7
10
|
git init'
|
8
11
|
end
|
9
12
|
|
13
|
+
# Creates default capistrano deployment files in the new project directory
|
10
14
|
def self.capify(path)
|
11
15
|
system "capify " + path
|
12
16
|
end
|
data/lib/skeletor/version.rb
CHANGED
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 6
|
8
|
-
-
|
9
|
-
version: 0.6.
|
8
|
+
- 4
|
9
|
+
version: 0.6.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Will McKenzie
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2011-09-
|
17
|
+
date: 2011-09-27 00:00:00 +01:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|