noe 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/noe/help.rb ADDED
@@ -0,0 +1,26 @@
1
+ module Noe
2
+ class Main
3
+ #
4
+ # Show help about a specific command
5
+ #
6
+ # SYNOPSIS
7
+ # #{program_name} #{command_name} COMMAND
8
+ #
9
+ class Help < Quickl::Command(__FILE__, __LINE__)
10
+
11
+ # Let NoSuchCommandError be passed to higher stage
12
+ no_react_to Quickl::NoSuchCommand
13
+
14
+ # Command execution
15
+ def execute(args)
16
+ if args.size != 1
17
+ puts super_command.help
18
+ else
19
+ cmd = has_command!(args.first, super_command)
20
+ puts cmd.help
21
+ end
22
+ end
23
+
24
+ end # class Help
25
+ end # class Main
26
+ end # module Noe
@@ -0,0 +1,89 @@
1
+ require 'fileutils'
2
+ module Noe
3
+ class Main
4
+ #
5
+ # Install default configuration and template.
6
+ #
7
+ # SYNOPSIS
8
+ # #{program_name} #{command_name} [--force] [FOLDER]
9
+ #
10
+ # OPTIONS
11
+ # #{summarized_options}
12
+ #
13
+ # DESCRIPTION
14
+ # This command will install Noe's default configuration under
15
+ # FOLDER/.noerc and a default ruby template under FOLDER/.noe.
16
+ # Unless stated otherwise, FOLDER is user's home.
17
+ #
18
+ # If FOLDER/.noerc already exists, the comand safely fails.
19
+ # Use --force to override existing configuration.
20
+ #
21
+ class Install < Quickl::Command(__FILE__, __LINE__)
22
+ include Noe::Commons
23
+
24
+ # Force mode ?
25
+ attr_reader :force
26
+
27
+ # Install options
28
+ options do |opt|
29
+ @force = false
30
+ opt.on('--force', '-f',
31
+ "Force overriding on all existing files"){
32
+ @force = true
33
+ }
34
+ end
35
+
36
+ def execute(args)
37
+ if args.size > 1
38
+ raise Quickl::InvalidArgument, "Needless arguments: #{args[1..-1].join(' ')}"
39
+ end
40
+ folder = args.first || ENV['HOME']
41
+
42
+ noerc_file = File.join(folder, '.noerc')
43
+ noe_folder = File.join(folder, '.noe')
44
+
45
+ # generate .noerc
46
+ if File.exists?(noerc_file) and not(force)
47
+ raise Noe::Error, "#{noerc_file} already exists, use --force to override"
48
+ end
49
+ File.open(noerc_file, 'w') do |out|
50
+ def_config = File.join(File.dirname(__FILE__), 'config.yaml')
51
+ context = { :templates_dir => noe_folder}
52
+ out << WLang::file_instantiate(def_config, context, 'wlang/active-string')
53
+ end
54
+
55
+ # generate .noe folder
56
+ unless File.exists?(noe_folder)
57
+ FileUtils.mkdir(noe_folder)
58
+ end
59
+
60
+ # copy default templates
61
+ tdir = File.expand_path('../../../templates', __FILE__)
62
+ Dir[File.join(tdir, '*')].each do |tpl|
63
+ target = File.join(noe_folder, File.basename(tpl))
64
+ if File.exists?(target)
65
+ if force
66
+ FileUtils.rm_rf target
67
+ else
68
+ puts "#{target} already exists, use --force to override"
69
+ next
70
+ end
71
+ end
72
+ FileUtils.cp_r tpl, noe_folder
73
+ end
74
+
75
+ # say something!
76
+ puts "Noe successfully installed !"
77
+ puts
78
+ puts "What's next?"
79
+ puts " * cat #{noerc_file}"
80
+ puts " * ls -lA #{noe_folder}"
81
+ puts " * noe list"
82
+ puts " * noe create hello_world"
83
+ puts
84
+ puts "Thank you for using Noe (v#{Noe::VERSION}), enjoy!"
85
+ end
86
+
87
+ end # class Install
88
+ end # class Main
89
+ end # module Noe
data/lib/noe/list.rb ADDED
@@ -0,0 +1,39 @@
1
+ module Noe
2
+ class Main
3
+ #
4
+ # List available templates.
5
+ #
6
+ # SYNOPSIS
7
+ # #{program_name} #{command_name}
8
+ #
9
+ # DESCRIPTION
10
+ # This command list project templates found in the templates folder.
11
+ # The later is checked as a side effect.
12
+ #
13
+ # TIP
14
+ # Run this command to know where templates are located!
15
+ #
16
+ class List < Quickl::Command(__FILE__, __LINE__)
17
+ include Noe::Commons
18
+
19
+ def execute(args)
20
+ unless args.empty?
21
+ raise Quickl::InvalidArgument, "Needless argument: #{args.join(', ')}"
22
+ end
23
+
24
+ puts "Templates located in: #{templates_dir}"
25
+ Dir[File.join(templates_dir, '**')].collect do |tpl_dir|
26
+ begin
27
+ tpl = Template.new(tpl_dir)
28
+ puts " * %-#{25}s %s" % [ "#{tpl.name} (v#{tpl.version})" , tpl.description ]
29
+ tpl
30
+ rescue => ex
31
+ puts " * %-#{25}s %s" % [File.basename(tpl_dir), ex.message]
32
+ nil
33
+ end
34
+ end
35
+ end
36
+
37
+ end # class List
38
+ end # class Main
39
+ end # module Noe
data/lib/noe/main.rb ADDED
@@ -0,0 +1,79 @@
1
+ module Noe
2
+ #
3
+ # Noe - A simple and extensible project generator
4
+ #
5
+ # SYNOPSIS
6
+ # #{program_name} [--version] [--help] COMMAND [cmd opts] ARGS...
7
+ #
8
+ # OPTIONS
9
+ # #{summarized_options}
10
+ #
11
+ # COMMANDS
12
+ # #{summarized_subcommands}
13
+ #
14
+ # DESCRIPTION
15
+ # Noe helps development via support for well-designed templates. See
16
+ # https://github.com/blambeau/noe for more information.
17
+ #
18
+ # See '#{program_name} help COMMAND' for more information on a specific command.
19
+ #
20
+ class Main < Quickl::Delegate(__FILE__, __LINE__)
21
+
22
+ # Configuration instance
23
+ attr_reader :config_file
24
+
25
+ # Show backtrace on error?
26
+ attr_reader :backtrace
27
+
28
+ # Returns Noe's configuration, loading it if required
29
+ def config
30
+ @config_file ||= find_config_file
31
+ Config.new(@config_file)
32
+ end
33
+
34
+ # Finds the configuration file and loads automatically
35
+ def find_config_file
36
+ in_home = File.join(ENV['HOME'], '.noerc')
37
+ File.file?(in_home) ? in_home : nil
38
+ end
39
+
40
+ # Install options
41
+ options do |opt|
42
+ # Set a specific configuration file to use
43
+ opt.on('--config=FILE',
44
+ 'Use a specific config file (defaults to ~/.noerc)') do |f|
45
+ @config_file = valid_read_file!(f)
46
+ end
47
+ # Show backtrace on error
48
+ opt.on_tail("--backtrace",
49
+ "Show backtrace on error") do
50
+ @backtrace = true
51
+ end
52
+ # Show the help and exit
53
+ opt.on_tail("--help",
54
+ "Show help") do
55
+ raise Quickl::Help
56
+ end
57
+ # Show version and exit
58
+ opt.on_tail("--version",
59
+ "Show version") do
60
+ raise Quickl::Exit, "#{program_name} #{Noe::VERSION} (c) 2011, Bernard Lambeau"
61
+ end
62
+ end
63
+
64
+ # Runs the command
65
+ def run(argv, requester = nil)
66
+ super
67
+ rescue Quickl::Error
68
+ raise
69
+ rescue Noe::Error => ex
70
+ puts "#{ex.class}: #{ex.message}"
71
+ puts ex.backtrace.join("\n") if backtrace
72
+ rescue StandardError => ex
73
+ puts "Oups, Noe encountered a serious problem! Please report if a bug."
74
+ puts "#{ex.class}: #{ex.message}"
75
+ puts ex.backtrace.join("\n")
76
+ end
77
+
78
+ end # class Main
79
+ end # module Noe
@@ -0,0 +1,144 @@
1
+ module Noe
2
+ class Template
3
+ include Enumerable
4
+
5
+ # Main folder of the template
6
+ attr_reader :folder
7
+
8
+ # Loaded specification
9
+ attr_reader :spec
10
+
11
+ # Creates a template instance
12
+ def initialize(folder)
13
+ @folder = folder
14
+ __load
15
+ end
16
+
17
+ # Loads the template from its folder
18
+ def __load
19
+ if File.file?(spec_file) and File.readable?(spec_file)
20
+ @spec = YAML::load(File.read(spec_file))
21
+ else
22
+ raise Noe::Error, "Unable to find template: #{spec_file}"
23
+ end
24
+ end
25
+
26
+ # Returns path to the spec file
27
+ def spec_file
28
+ File.join(folder, "noespec.yaml")
29
+ end
30
+
31
+ # Returns template name
32
+ def name
33
+ File.basename(folder)
34
+ end
35
+
36
+ # Returns template description
37
+ def description
38
+ spec['template-info']['description']
39
+ end
40
+
41
+ # Returns template version
42
+ def version
43
+ spec['template-info']['version']
44
+ end
45
+
46
+ # Returns path to the sources folder
47
+ def src_folder
48
+ File.join(folder, "src")
49
+ end
50
+
51
+ # Ignore some file?
52
+ def ignore?(file)
53
+ ['.', '..'].include? File.basename(file)
54
+ end
55
+
56
+ # Returns an entry for a given relative path
57
+ def entry(*paths)
58
+ Entry.new(self, paths.join(File::PATH_SEPARATOR))
59
+ end
60
+
61
+ # Visit the template
62
+ def visit(entry = src_folder, &block)
63
+ if entry.is_a?(Entry)
64
+ block.call(entry)
65
+ else
66
+ entry = Entry.new(self, nil)
67
+ end
68
+ if entry.directory?
69
+ Dir.foreach(entry.realpath) do |child|
70
+ childentry = entry.child_entry(child)
71
+ unless ignore?(childentry.realpath)
72
+ visit(childentry, &block)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ alias :each :visit
78
+
79
+ private :__load
80
+
81
+ # Entry inside a template structure
82
+ class Entry
83
+
84
+ # Template where this entry is located
85
+ attr_reader :template
86
+
87
+ # Relative path of the entry inside the template
88
+ attr_reader :path
89
+
90
+ # Creates an entry instance
91
+ def initialize(template, path)
92
+ @template = template
93
+ @path = path
94
+ end
95
+
96
+ # Returns real absolute path of the entry
97
+ def realpath
98
+ path.nil? ? template.src_folder : File.join(template.src_folder, path)
99
+ end
100
+
101
+ # Returns entry name
102
+ def name
103
+ File.basename(realpath)
104
+ end
105
+
106
+ # Relocate the path according to variables
107
+ def relocate(variables)
108
+ path.split(File::PATH_SEPARATOR).
109
+ collect{|v| rename_one(variables, v)}.
110
+ join(File::PATH_SEPARATOR)
111
+ end
112
+
113
+ # Returns the target name, according to some variables
114
+ def rename_one(variables, name = self.name)
115
+ if name =~ /__([a-z]+)__/
116
+ if x = variables[$1]
117
+ name.gsub(/__([a-z]+)__/, x)
118
+ else
119
+ raise Noe::Error, "Missing variable #{$1}"
120
+ end
121
+ else
122
+ name
123
+ end
124
+ end
125
+
126
+ # Is the entry a file?
127
+ def file?
128
+ File.file?(realpath)
129
+ end
130
+
131
+ # Is the entry a directory?
132
+ def directory?
133
+ File.directory?(realpath)
134
+ end
135
+
136
+ # Builds an child entry for a given name
137
+ def child_entry(name)
138
+ template.entry(path.nil? ? name : File.join(path, name))
139
+ end
140
+
141
+ end # class Entry
142
+
143
+ end # class Template
144
+ end # module Noe
data/noe.gemspec ADDED
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../lib/noe', __FILE__)
2
+ spec = Gem::Specification.new do |s|
3
+ s.name = %q{noe}
4
+ s.version = Noe::VERSION.dup
5
+ s.date = Time.now.strftime('%Y-%m-%d')
6
+
7
+ s.author = %q{Bernard Lambeau}
8
+ s.email = %q{blambeau@gmail.com}
9
+
10
+ s.description = %q{A simple and extensible project generator}
11
+ s.summary = %q{Noe helps development by providing support for project templates and instantiation.}
12
+
13
+ s.require_paths = ["lib"]
14
+ s.bindir = "bin"
15
+ s.executables = ["noe"]
16
+
17
+ s.extra_rdoc_files = ["README.md", "CHANGELOG.md"]
18
+
19
+ s.files =
20
+ Dir['bin/**/*'] +
21
+ Dir['lib/**/*'] +
22
+ Dir['spec/**/*'] +
23
+ Dir['templates/**/*'] +
24
+ %w{ noe.gemspec Rakefile README.md CHANGELOG.md LICENCE.txt}
25
+
26
+ s.add_dependency('wlang', '>= 0.9.2')
27
+ s.add_dependency('quickl', '>= 0.2.0')
28
+
29
+ s.add_development_dependency('rake')
30
+ s.add_development_dependency('rspec', ">= 2.4.0")
31
+ s.add_development_dependency('yard', ">= 0.6.4")
32
+ s.add_development_dependency('bluecloth', ">= 0.6.4")
33
+
34
+ s.homepage = %q{http://github.com/blambeau/noe}
35
+ end
36
+
data/spec/noe_spec.rb ADDED
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+ describe Noe do
3
+
4
+ it "should have a version number" do
5
+ Noe.const_defined?(:VERSION).should be_true
6
+ end
7
+
8
+ end
@@ -0,0 +1,4 @@
1
+ $LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
2
+ require 'rubygems'
3
+ require 'rspec'
4
+ require 'noe'
@@ -0,0 +1,41 @@
1
+ require File.expand_path('../../../spec_helper', __FILE__)
2
+ module Noe
3
+ describe "Template::Entry#relocate" do
4
+
5
+ let(:template){
6
+ Template.new(File.expand_path('../../../../templates/ruby', __FILE__))
7
+ }
8
+ let(:vars){
9
+ {"lower" => "project"}
10
+ }
11
+ subject{
12
+ entry.relocate(vars)
13
+ }
14
+
15
+ describe "when nothing has to change" do
16
+ let(:entry){ template.entry('.gitignore') }
17
+ it{ should == ".gitignore" }
18
+ end
19
+
20
+ describe "when exactly a replacement" do
21
+ let(:entry){ template.entry("__lower__") }
22
+ it { should == "project" }
23
+ end
24
+
25
+ describe "when a replacement inside something else" do
26
+ let(:entry){ template.entry("__lower___spec.rb") }
27
+ it { should == "project_spec.rb" }
28
+ end
29
+
30
+ describe "when no replace and sub file" do
31
+ let(:entry){ template.entry("lib", "README.md") }
32
+ it { should == ["lib", "README.md"].join(File::PATH_SEPARATOR) }
33
+ end
34
+
35
+ describe "when no replace and sub file with replacement" do
36
+ let(:entry){ template.entry("lib", "__lower__.rb") }
37
+ it { should == ["lib", "project.rb"].join(File::PATH_SEPARATOR) }
38
+ end
39
+
40
+ end
41
+ end # module Noe