cog 0.0.15 → 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
data/bin/cog CHANGED
@@ -4,12 +4,15 @@ $LOAD_PATH << File.join(File.dirname(__FILE__), '..', 'lib')
4
4
  require 'cog'
5
5
  require 'active_support/core_ext'
6
6
  require 'fileutils'
7
+ require 'rainbow'
7
8
 
8
9
  include GLI::App
9
10
 
10
11
  program_desc 'This is a utility to help you write code generators.'
11
12
 
12
13
  # version Cog::VERSION
14
+ desc 'Output more detailed information when running a command'
15
+ switch :v
13
16
 
14
17
  desc 'Add cog to the project in the present working directory'
15
18
  skips_pre
@@ -22,7 +25,7 @@ end
22
25
 
23
26
  desc 'Create a generator (or leave name blank to list project generators)'
24
27
  arg_name 'name'
25
- command :generator do |c|
28
+ command [:generator, :gen] do |c|
26
29
 
27
30
  c.desc 'which tool to use to create the generator'
28
31
  c.arg_name 'tool_name'
@@ -32,14 +35,12 @@ command :generator do |c|
32
35
  c.action do |global_options, options, args|
33
36
  if args.empty?
34
37
  # List
35
- x = Cog::Generator.list
36
- puts x.collect {|gen| " #{gen}"}.join "\n" unless x.empty?
38
+ x = Cog::Generator.list global_options[:v]
39
+ puts x.join "\n" unless x.empty?
37
40
  else
38
41
  # Create
39
42
  args.each do |name|
40
- unless Cog::Generator.create name, options
41
- puts "Failed to create generator #{name}"
42
- end
43
+ Cog::Generator.create name, :tool => options[:tool], :verbose => global_options[:v]
43
44
  end
44
45
  end
45
46
  end
@@ -52,47 +53,39 @@ command :tool do |c|
52
53
 
53
54
  c.action do |global_options, options, args|
54
55
  if args.empty?
55
- puts 'Available tools:'
56
- puts (Cog::Tool.list.collect {|tool| " #{tool}"}.join "\n")
56
+ # List
57
+ x = Cog::Tool.list global_options[:v]
58
+ puts x.join "\n" unless x.empty?
57
59
  else
60
+ # Create
58
61
  args.each do |name|
59
- unless File.exists? name
60
- Cog::Tool.create name
61
- else
62
- puts "Could not create tool for '#{name}', a file or directory already exists with that name"
63
- end
62
+ Cog::Tool.create name
64
63
  end
65
64
  end
66
65
  end
67
66
  end
68
67
 
69
- desc 'List supported languages'
70
- skips_pre
71
- command :languages do |c|
72
-
73
- c.action do
74
- puts 'c++'
75
- end
76
- end
77
-
78
68
  desc 'Run generators in the current project'
79
69
  arg_name 'generator_name'
80
70
  command :run do |c|
81
71
 
82
72
  c.action do |global_options, options, args|
83
73
  args = Cog::Generator.list if args.empty?
84
- args.each do |gen|
85
- filename = File.join Cog::Config.instance.project_generators_path, "#{gen}.rb"
86
- if File.exists? filename
87
- puts "Running generator #{gen}"
88
- require filename
89
- else
90
- puts "No such generator #{gen}"
91
- end
74
+ args.each do |name|
75
+ Cog::Generator.run name, :verbose => global_options[:v]
92
76
  end
93
77
  end
94
78
  end
95
79
 
80
+ desc 'List supported languages'
81
+ skips_pre
82
+ command :languages do |c|
83
+
84
+ c.action do
85
+ puts 'c++'
86
+ end
87
+ end
88
+
96
89
  pre do |global_options, command, options, args|
97
90
  # Pre logic here
98
91
  # Return true to proceed; false to abort and not call the
@@ -100,7 +93,8 @@ pre do |global_options, command, options, args|
100
93
  # Use skips_pre before a command to skip this block
101
94
  # on that command only
102
95
  unless Cog::Config.instance.project?
103
- puts 'No Cogfile could be found. Run `cog init` to prepare an existing project.'
96
+ STDERR.write "No Cogfile could be found\n".color(:red)
97
+ STDOUT.write "Run `cog init` to prepare a project for use with cog\n"
104
98
  false
105
99
  else
106
100
  true
@@ -119,4 +113,9 @@ on_error do |exception|
119
113
  true
120
114
  end
121
115
 
122
- exit run(ARGV)
116
+ begin
117
+ exit run(ARGV)
118
+ rescue
119
+ # Don't show stack traces during normal use
120
+ raise unless ENV['COG_DEBUG'].nil? || /^(|0|false|no|off)$/i =~ ENV['COG_DEBUG']
121
+ end
@@ -1,6 +1,7 @@
1
1
  require 'cog/config'
2
2
  require 'cog/errors'
3
3
  require 'erb'
4
+ require 'rainbow'
4
5
 
5
6
  module Cog
6
7
 
@@ -12,11 +13,10 @@ module Cog
12
13
  module Generator
13
14
 
14
15
  # A list of available project generators
15
- def self.list
16
+ def self.list(verbose=false)
16
17
  if Config.instance.project?
17
- Dir.glob(File.join Config.instance.project_generators_path, '*.rb').collect do |path|
18
- File.basename(path).slice(0..-4)
19
- end
18
+ x = Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
19
+ verbose ? x : (x.collect {|path| File.basename(path).slice(0..-4)})
20
20
  else
21
21
  []
22
22
  end
@@ -37,15 +37,43 @@ module Cog
37
37
  return false unless Config.instance.project?
38
38
  gen_name = File.join Config.instance.project_generators_path, "#{name}.rb"
39
39
  template_name = File.join Config.instance.project_templates_path, "#{name}.txt.erb"
40
- return false if File.exists?(gen_name) || File.exists?(template_name)
41
- Object.new.instance_eval do
42
- extend Generator
43
- @name = name
44
- @class_name = name.to_s.camelize
45
- stamp 'cog/generator/basic.rb', gen_name, :absolute_destination => true
46
- stamp 'cog/generator/basic-template.txt.erb', template_name, :absolute_destination => true
40
+ if File.exists? gen_name
41
+ STDERR.write "Generator '#{gen_name}' already exists\n".color(:red)
42
+ false
43
+ elsif File.exists? template_name
44
+ STDERR.write "Template '#{template_name}' already exists\n".color(:red)
45
+ false
46
+ else
47
+ Object.new.instance_eval do
48
+ extend Generator
49
+ @name = name
50
+ @class_name = name.to_s.camelize
51
+ stamp 'cog/generator/basic.rb', gen_name, :absolute_destination => true
52
+ stamp 'cog/generator/basic-template.txt.erb', template_name, :absolute_destination => true
53
+ end
54
+ true
55
+ end
56
+ end
57
+
58
+ # Run the generator with the given name
59
+ #
60
+ # ==== Arguments
61
+ # * +name+ - the name of the generator
62
+ #
63
+ # ==== Returns
64
+ # Whether or not the generator could be found
65
+ def self.run(name, opt={})
66
+ filename = File.join Cog::Config.instance.project_generators_path, "#{name}.rb"
67
+ if File.exists? filename
68
+ require filename
69
+ return true
47
70
  end
48
- true
71
+ STDERR.write "No such generator '#{name}'\n".color(:red)
72
+ false
73
+ rescue => e
74
+ trace = opt[:verbose] ? "\n#{e.backtrace.join "\n"}" : ''
75
+ STDERR.write "Generator '#{name}' failed: #{e}#{trace}\n".color(:red)
76
+ false
49
77
  end
50
78
 
51
79
  # Get the template with the given name.
@@ -93,8 +121,9 @@ module Cog
93
121
  if same? dest, scratch
94
122
  FileUtils.rm scratch
95
123
  else
96
- puts "Generated #{dest}"
124
+ updated = File.exists? dest
97
125
  FileUtils.mv scratch, dest
126
+ STDOUT.write "#{updated ? :Updated : :Created} #{dest}\n".color(updated ? :white : :green)
98
127
  end
99
128
  nil
100
129
  end
@@ -103,7 +132,7 @@ module Cog
103
132
  def copy_if_missing(src, dest)
104
133
  unless File.exists? dest
105
134
  FileUtils.cp src, dest
106
- puts "Created #{dest}"
135
+ STDOUT.write "Created #{dest}".color(:white)
107
136
  end
108
137
  end
109
138
 
@@ -112,7 +141,7 @@ module Cog
112
141
  path = File.join path_components
113
142
  unless File.exists? path
114
143
  FileUtils.mkdir_p path
115
- puts "Created #{path}"
144
+ STDOUT.write "Created #{path}".color(:white)
116
145
  end
117
146
  end
118
147
 
@@ -48,7 +48,12 @@ module Cog
48
48
 
49
49
  # Path to the generator with the given name
50
50
  def generator(name)
51
- File.join active_fixture_dir, 'cog', 'generators', "#{name}.rb"
51
+ File.expand_path File.join(active_fixture_dir, 'cog', 'generators', "#{name}.rb")
52
+ end
53
+
54
+ # Path to the test tool with the given name
55
+ def tool(name)
56
+ File.expand_path File.join(spec_root, 'tools', name.to_s)
52
57
  end
53
58
 
54
59
  # The next cog spec will execute in a fresh copy of the given fixture directory.
@@ -56,7 +61,7 @@ module Cog
56
61
  def use_fixture(name)
57
62
  path = File.join spec_root, 'fixtures', name.to_s
58
63
  if File.exists?(path) && File.directory?(path)
59
- FileUtils.rmtree active_fixture_dir if File.exists? active_fixture_dir
64
+ FileUtils.rm_rf active_fixture_dir if File.exists? active_fixture_dir
60
65
  FileUtils.cp_r path, active_fixture_dir
61
66
  Dir.chdir active_fixture_dir
62
67
  else
@@ -8,18 +8,18 @@ module Cog
8
8
  # Check out #match_maker for help writing new matchers.
9
9
  module Matchers
10
10
 
11
- # The target Invocation should complain about a missing +Cogfile+
12
- def complain_about_missing_cogfile
11
+ # The target Invocation should write something to STDERR, indicating an error
12
+ def complain
13
13
  match_maker do
14
- message { "to [require|not require] a Cogfile. STDOUT: #{lines.inspect}" }
15
- test { (/no cogfile could be found/i =~ lines.first) }
14
+ message { "to [write something|not write anything] to STDERR" }
15
+ test { !error.empty? }
16
16
  end
17
17
  end
18
18
 
19
19
  # The target Invocation should create a +Cogfile+ where none existed before
20
20
  def make(path)
21
21
  match_maker do
22
- message { "to [create|not create] #{path}. STDOUT: #{lines.inspect}" }
22
+ message { "to [create|not create] #{path}" }
23
23
  before do
24
24
  @existed = File.exists? path
25
25
  end
@@ -32,15 +32,25 @@ module Cog
32
32
  # The target Invocation should do something, as determined by standard output
33
33
  def do_something
34
34
  match_maker do
35
- message { "to [write something|not write anything] to stdout. STDOUT: #{lines.inspect}" }
35
+ message { "to [write something|not write anything] to STDOUT" }
36
36
  test { !lines.empty? }
37
37
  end
38
38
  end
39
39
 
40
+ # The target Invocation should write the given list of lines to standard output
41
+ def output(x)
42
+ match_maker do
43
+ message { "to [write|not write] #{x.join "\n"} to STDOUT"}
44
+ test do
45
+ lines.zip(x).all? {|a, b| a.strip == b.to_s.strip}
46
+ end
47
+ end
48
+ end
49
+
40
50
  # The target Invocation should output the default help text
41
51
  def show_help
42
52
  match_maker do
43
- message { "to [show|not show] the default help text, got #{lines.first.inspect}. STDOUT: #{lines.inspect}" }
53
+ message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
44
54
  test { (/help.*code gen/ =~ lines[1]) }
45
55
  end
46
56
  end
@@ -5,9 +5,13 @@ module Cog
5
5
  # Within Matchers#match_maker blocks, +self+ is set to an instance of this
6
6
  # class.
7
7
  class MatchMaker
8
- # A list of lines read from standard output after executing the Invocation.
8
+
9
+ # A list of lines read from STDOUT after executing the Invocation
9
10
  attr_reader :lines
10
11
 
12
+ # A list of lines read from STDERR after executing the Invocation
13
+ attr_reader :error
14
+
11
15
  # Define a block which runs after a test fails and should return
12
16
  # a failure message template.
13
17
  #
@@ -44,18 +48,23 @@ module Cog
44
48
  instance_eval &@before_block unless @before_block.nil?
45
49
  @runner.exec do |input, output, error|
46
50
  @lines = output.readlines
51
+ @error = error.readlines
47
52
  end
48
53
  instance_eval &@test_block
49
54
  end
50
55
  def failure_message # :nodoc:
51
56
  msg = instance_eval &@msg_block
52
57
  msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\1'
53
- "expected #{@runner} #{msg}"
58
+ "expected #{@runner} #{msg}\n#{trace}"
54
59
  end
55
60
  def negative_failure_message # :nodoc:
56
61
  msg = instance_eval &@msg_block
57
62
  msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\2'
58
- "expected #{@runner} #{msg}"
63
+ "expected #{@runner} #{msg}\n#{trace}"
64
+ end
65
+
66
+ def trace # :nodoc
67
+ "STDOUT:\n#{@lines.join "\n"}\nSTDERR:\n#{@error.join "\n"}"
59
68
  end
60
69
  end
61
70
 
@@ -6,8 +6,12 @@ module Cog
6
6
  # Points to the +cog+ command-line app
7
7
  class Runner
8
8
 
9
+ # Value of the COG_TOOLS environment variable for invocations returned from #run
10
+ attr_accessor :tools
11
+
9
12
  def initialize(path_to_cl_app)
10
13
  @cog = File.expand_path path_to_cl_app
14
+ @tools = []
11
15
  end
12
16
 
13
17
  # Run cog with the given arguments
@@ -16,8 +20,8 @@ module Cog
16
20
  # An instance of Invocation configured with the arguments. Use should and
17
21
  # should_not with the custom Matchers
18
22
  def run(*args)
19
- args = ['bundle', 'exec', @cog] + args
20
- Invocation.new(args.collect {|x| x.to_s})
23
+ args = [@cog] + args
24
+ Invocation.new(args.collect {|x| x.to_s}, :tools => @tools)
21
25
  end
22
26
  end
23
27
 
@@ -26,19 +30,21 @@ module Cog
26
30
  # object returned by Runner#run.
27
31
  class Invocation
28
32
 
29
- def initialize(cmd) # :nodoc:
33
+ def initialize(cmd, opt={}) # :nodoc:
30
34
  @cmd = cmd
35
+ @tools = opt[:tools].join ':'
31
36
  end
32
37
 
33
38
  def exec(*args, &block) # :nodoc:
34
- @s = ([File.basename @cmd[2]] + @cmd.slice(3..-1)).join ' '
39
+ @cmd = ['bundle', 'exec'] + @cmd
40
+ ENV['COG_TOOLS'] = @tools
35
41
  Open3.popen3 *@cmd do |i,o,e,t|
36
42
  block.call i,o,e
37
43
  end
38
44
  end
39
45
 
40
46
  def to_s # :nodoc:
41
- "`#{@s}`"
47
+ "`COG_TOOLS=#{@tools} #{@cmd.compact.join ' '}`"
42
48
  end
43
49
  end
44
50
 
@@ -1,5 +1,6 @@
1
1
  require 'cog/config'
2
2
  require 'cog/generator'
3
+ require 'rainbow'
3
4
 
4
5
  module Cog
5
6
 
@@ -7,30 +8,54 @@ module Cog
7
8
  class Tool
8
9
 
9
10
  # A list of available tools
10
- def self.list
11
- # TODO: use paths to instantiate a list of Tool objects
12
- paths = ENV['COG_TOOLS'] || []
11
+ def self.list(verbose=false)
12
+ x = (ENV['COG_TOOLS'] || '').split ':'
13
+ if x.all? {|path| File.exists?(path) && File.directory?(path)}
14
+ if verbose
15
+ x.collect {|path| File.expand_path path}
16
+ else
17
+ x.collect {|path| File.basename path}
18
+ end
19
+ else
20
+ x.each do |path|
21
+ if !File.exists? path
22
+ STDERR.write "No such cog tool at path '#{path}'\n".color(:red)
23
+ elsif !File.directory? path
24
+ STDERR.write "Not a cog tool at path '#{path}'\n".color(:red)
25
+ end
26
+ end
27
+ []
28
+ end
13
29
  end
14
30
 
15
31
  # Generate a new tool with the given name
32
+ #
33
+ # ==== Returns
34
+ # Whether or not the generator was created successfully
16
35
  def self.create(name)
17
- Object.new.instance_eval do
18
- class << self ; include Generator ; end
19
- @name = name.to_s.downcase
20
- @module_name = name.to_s.capitalize
21
- @author = '<Your name goes here>'
22
- @email = 'youremail@...'
23
- @description = 'A one-liner'
24
- @cog_version = Cog::VERSION
25
- stamp 'cog/tool/tool.rb', "#{@name}/lib/#{@name}.rb", :absolute_destination => true
26
- stamp 'cog/tool/version.rb', "#{@name}/lib/#{@name}/version.rb", :absolute_destination => true
27
- stamp 'cog/tool/generator.rb', "#{@name}/cog/templates/#{@name}/generator.rb.erb", :absolute_destination => true
28
- stamp 'cog/tool/Gemfile', "#{@name}/Gemfile", :absolute_destination => true
29
- stamp 'cog/tool/Rakefile', "#{@name}/Rakefile", :absolute_destination => true
30
- stamp 'cog/tool/tool.gemspec', "#{@name}/#{@name}.gemspec", :absolute_destination => true
31
- stamp 'cog/tool/API.rdoc', "#{@name}/API.rdoc", :absolute_destination => true
32
- stamp 'cog/tool/LICENSE', "#{@name}/LICENSE", :absolute_destination => true
33
- stamp 'cog/tool/README.markdown', "#{@name}/README.markdown", :absolute_destination => true
36
+ if File.exists? name
37
+ STDERR.write "A #{File.directory?(name) ? :directory : :file} named '#{name}' already exists\n".color(:red)
38
+ false
39
+ else
40
+ Object.new.instance_eval do
41
+ extend Generator
42
+ @name = name.to_s.downcase
43
+ @module_name = name.to_s.capitalize
44
+ @author = '<Your name goes here>'
45
+ @email = 'youremail@...'
46
+ @description = 'A one-liner'
47
+ @cog_version = Cog::VERSION
48
+ stamp 'cog/tool/tool.rb', "#{@name}/lib/#{@name}.rb", :absolute_destination => true
49
+ stamp 'cog/tool/version.rb', "#{@name}/lib/#{@name}/version.rb", :absolute_destination => true
50
+ stamp 'cog/tool/generator.rb', "#{@name}/cog/templates/#{@name}/generator.rb.erb", :absolute_destination => true
51
+ stamp 'cog/tool/Gemfile', "#{@name}/Gemfile", :absolute_destination => true
52
+ stamp 'cog/tool/Rakefile', "#{@name}/Rakefile", :absolute_destination => true
53
+ stamp 'cog/tool/tool.gemspec', "#{@name}/#{@name}.gemspec", :absolute_destination => true
54
+ stamp 'cog/tool/API.rdoc', "#{@name}/API.rdoc", :absolute_destination => true
55
+ stamp 'cog/tool/LICENSE', "#{@name}/LICENSE", :absolute_destination => true
56
+ stamp 'cog/tool/README.markdown', "#{@name}/README.markdown", :absolute_destination => true
57
+ end
58
+ true
34
59
  end
35
60
  end
36
61
  end
@@ -1,3 +1,3 @@
1
1
  module Cog
2
- VERSION = '0.0.15' unless const_defined? :VERSION
2
+ VERSION = '0.0.16' unless const_defined? :VERSION
3
3
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cog
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
4
+ hash: 63
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 15
10
- version: 0.0.15
9
+ - 16
10
+ version: 0.0.16
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kevin Tonon
@@ -18,7 +18,7 @@ cert_chain: []
18
18
  date: 2012-11-04 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
- name: rake
21
+ name: gli
22
22
  prerelease: false
23
23
  requirement: &id001 !ruby/object:Gem::Requirement
24
24
  none: false
@@ -29,10 +29,10 @@ dependencies:
29
29
  segments:
30
30
  - 0
31
31
  version: "0"
32
- type: :development
32
+ type: :runtime
33
33
  version_requirements: *id001
34
34
  - !ruby/object:Gem::Dependency
35
- name: rdoc
35
+ name: rainbow
36
36
  prerelease: false
37
37
  requirement: &id002 !ruby/object:Gem::Requirement
38
38
  none: false
@@ -43,8 +43,36 @@ dependencies:
43
43
  segments:
44
44
  - 0
45
45
  version: "0"
46
- type: :development
46
+ type: :runtime
47
47
  version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rake
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: rdoc
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
48
76
  description:
49
77
  email: kevin@betweenconcepts.com
50
78
  executables: