cog 0.0.15 → 0.0.16

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/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: