cog 0.0.19 → 0.0.20

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/cog.rb CHANGED
@@ -4,11 +4,13 @@ require 'cog/tool'
4
4
  require 'cog/version'
5
5
  require 'fileutils'
6
6
 
7
- # The static methods on this top level module mirror the commands available to
8
- # the +cog+ command line utility.
7
+ # +cog+ is a command line utility that makes it a bit easier to organize a project
8
+ # which uses code generation. These are the API docs, but you might want to read
9
+ # the {https://github.com/ktonon/cog#readme general introduction} first.
9
10
  module Cog
10
11
 
11
12
  # Prepare the project in the present working directory for use with +cog+
13
+ # @return [nil]
12
14
  def self.initialize_project
13
15
  Object.new.instance_eval do
14
16
  class << self ; include Generator ; end
@@ -16,6 +18,7 @@ module Cog
16
18
  config = Config.instance
17
19
  touch_path config.project_generators_path
18
20
  touch_path config.project_templates_path
21
+ nil
19
22
  end
20
23
  end
21
24
 
@@ -3,50 +3,57 @@ require 'singleton'
3
3
 
4
4
  module Cog
5
5
 
6
- # This is a low level interface. It is mainly used by the Generator methods
6
+ # This is a low level interface. It is mainly used by the {Generator} methods
7
7
  # to determine where to find things, and where to put them. When +cog+ is used
8
- # in a project the values of the singleton Config::instance should be configured using
9
- # a Cogfile.
8
+ # in a project the values of the singleton {Config.instance} should be configured using
9
+ # a {Cogfile}.
10
10
  class Config
11
11
 
12
- # Path to the project's +Cogfile+.
12
+ # @return [String] path to the project's {Cogfile}
13
13
  attr_reader :cogfile_path
14
14
 
15
- # Default language in which to generated application source code
15
+ # @return [String] default language in which to generated application source code
16
16
  attr_reader :language
17
17
 
18
- # Directory in which to find project generators
18
+ # @return [String] directory in which to find project generators
19
19
  attr_reader :project_generators_path
20
20
 
21
- # Directory in which the project's +Cogfile+ is found
21
+ # @return [String] directory in which the project's {Cogfile} is found
22
22
  attr_reader :project_root
23
23
 
24
- # Directory to which project source code is generated
24
+ # @return [String] directory to which project source code is generated
25
25
  attr_reader :project_source_path
26
26
 
27
- # Directory in which to find custom project templates
27
+ # @return [String] directory in which to find custom project templates
28
28
  attr_reader :project_templates_path
29
29
 
30
- # Are we operating in the context of a project?
31
- # That is, could a Cogfile be found?
30
+ # @return [Boolean] are we operating in the context of a project?
32
31
  def project?
33
32
  !@project_root.nil?
34
33
  end
35
34
 
36
- # A value which is set by the active tool
35
+ # @param value [String] a value which is set by the active tool
37
36
  attr_writer :tool_templates_path
38
37
 
39
- # A value which is set by the active tool
38
+ # @return [String] a value which is set by the active tool
40
39
  attr_accessor :tool_generator_template
41
40
 
42
- # A list of directories in which to find ERB template files.
43
- # Priority should be given first to last.
41
+ # A list of directories in which to find ERB template files
42
+ #
43
+ # Templates should be looked for in the following order as determined by the list returned from this method
44
+ #
45
+ # * {#project_templates_path}, present if we are in the context of a {#project?}
46
+ # * tool templates, present if we are in the context of a tool (i.e. a tool has set {#tool_templates_path=})
47
+ # * +cog+ built-in templates, always present
48
+ #
49
+ # @return [Array<String>] a list of directories order with ascending priority
44
50
  def template_paths
45
51
  [@project_templates_path, @tool_templates_path, File.join(Config.gem_dir, 'templates')].compact
46
52
  end
47
53
 
48
54
  # Location of the installed cog gem
49
- def self.gem_dir # :nodoc:
55
+ # @return [String] path to the cog gem
56
+ def self.gem_dir
50
57
  spec = Gem.loaded_specs['cog']
51
58
  if spec.nil?
52
59
  # The current __FILE__ is:
@@ -57,18 +64,17 @@ module Cog
57
64
  end
58
65
  end
59
66
 
60
- # The singleton instance.
67
+ # The singleton instance
61
68
  #
62
69
  # Initialized using the Cogfile for the current project, if any can be
63
- # found. If not, then #project? will be +false+ and all the +project_...+
70
+ # found. If not, then {#project?} will be +false+ and all the +project_...+
64
71
  # attributes will be +nil+.
65
72
  #
66
73
  # The Cogfile will be looked for in the present working directory. If none
67
74
  # is found there the parent directory will be checked, and then the
68
75
  # grandparent, and so on.
69
76
  #
70
- # ==== Returns
71
- # An instance of Config.
77
+ # @return [Config] the singleton Config instance
72
78
  def self.instance
73
79
  return @instance if @instance
74
80
  @instance = self.new
@@ -3,32 +3,35 @@ module Cog
3
3
 
4
4
  # In your project's +Cogfile+, +self+ has been set to an instance of this class.
5
5
  #
6
- # ==== Example +Cogfile+
6
+ # Typing <tt>cog init</tt> will create a +Cogfile+ in the present working directory.
7
+ # +Cogfile+ files are used to configure an instance of {Config}.
8
+ #
9
+ # @example
7
10
  # project_generators_path 'cog/generators'
8
11
  # project_templates_path 'cog/templates'
9
12
  # project_source_path 'src'
10
13
  # language 'c++'
11
14
  #
12
- # Typing `cog init` will create a +Cogfile+ in the present working directory.
13
- #
14
- # +Cogfile+ files are used to configure an instance of Config.
15
15
  class Cogfile
16
-
17
- def initialize(config) # :nodoc:
16
+
17
+ # Initialize with an instance of {Config}
18
+ # @api developer
19
+ # @param config [Config] the object which will be configured by this Cogfile
20
+ def initialize(config)
18
21
  @config = config
19
22
  end
20
23
 
21
- # Interpret the Cogfile and initialize @config
22
- def interpret # :nodoc:
24
+ # Interpret the +Cogfile+ at {Config#cogfile_path}
25
+ # @api developer
26
+ def interpret
23
27
  eval File.read(@config.cogfile_path), binding
24
28
  rescue Exception => e
25
29
  raise CogfileError.new(e.to_s)
26
30
  end
27
31
 
28
32
  # Define the directory in which to find project generators
29
- # ==== Arguments
30
- # * +path+ - A file system path
31
- # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
33
+ # @param path [String] a file system path
34
+ # @param absolute [Boolean] if +false+, the path is relative to {Config#project_root}
32
35
  def project_generators_path(path, absolute=false)
33
36
  @config.instance_eval do
34
37
  @project_generators_path = absolute ? path : File.join(project_root, path)
@@ -36,9 +39,8 @@ module Cog
36
39
  end
37
40
 
38
41
  # Define the directory in which to find custom project templates
39
- # ==== Arguments
40
- # * +path+ - A file system path
41
- # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
42
+ # @param path [String] a file system path
43
+ # @param absolute [Boolean] if +false+, the path is relative to {Config#project_root}
42
44
  def project_templates_path(path, absolute=false)
43
45
  @config.instance_eval do
44
46
  @project_templates_path = absolute ? path : File.join(project_root, path)
@@ -46,9 +48,8 @@ module Cog
46
48
  end
47
49
 
48
50
  # Define the directory to which project source code is generated
49
- # ==== Arguments
50
- # * +path+ - A file system path
51
- # * +absolute+ - If false, the path is relative to the directory containing the +Cogfile+
51
+ # @param path [String] a file system path
52
+ # @param absolute [Boolean] if +false+, the path is relative to {Config#project_root}
52
53
  def project_source_path(path, absolute=false)
53
54
  @config.instance_eval do
54
55
  @project_source_path = absolute ? path : File.join(project_root, path)
@@ -56,8 +57,7 @@ module Cog
56
57
  end
57
58
 
58
59
  # Define the default language in which to generated application source code
59
- # ==== Arguments
60
- # * +lang+ - A code for the language. Acceptable values are <tt>c++</tt>.
60
+ # @param lang [String] a code for the language. Acceptable values are <tt>c++</tt>
61
61
  def language(lang)
62
62
  @config.instance_eval do
63
63
  @language = lang
@@ -65,7 +65,8 @@ module Cog
65
65
  end
66
66
  end
67
67
 
68
- # For wrapping errors which occur during the processing of a +Cogfile+.
68
+ # For wrapping errors which occur during the processing of a {Cogfile}
69
+ # @api client
69
70
  class CogfileError < StandardError
70
71
  def message
71
72
  "in Cogfile, " + super
@@ -1,5 +1,6 @@
1
1
  require 'cog/config'
2
2
  require 'cog/errors'
3
+ require 'cog/helpers'
3
4
  require 'erb'
4
5
  require 'rainbow'
5
6
 
@@ -7,12 +8,14 @@ module Cog
7
8
 
8
9
  # This module defines an interface which can be used by generator objects.
9
10
  # Specifically, it makes it easy to find ERB templates and render them into
10
- # generated source code files, using the #stamp method.
11
+ # generated source code files, using the {#stamp} method.
11
12
  #
12
- # For more details on writing generators see https://github.com/ktonon/cog#generators
13
+ # @see https://github.com/ktonon/cog#generators Introduction to Generators
13
14
  module Generator
14
15
 
15
- # A list of available project generators
16
+ # List the available project generators
17
+ # @param verbose [Boolean] should full generator paths be listed?
18
+ # @return [Array<String>] a list of generator names
16
19
  def self.list(verbose=false)
17
20
  if Config.instance.project?
18
21
  x = Dir.glob(File.join Config.instance.project_generators_path, '*.rb')
@@ -23,15 +26,9 @@ module Cog
23
26
  end
24
27
 
25
28
  # Create a new generator
26
- #
27
- # ==== Arguments
28
- # * +name+ - the name to use for the new generator
29
- #
30
- # ==== Options
31
- # * +tool+ - the name of the tool to use (default: basic)
32
- #
33
- # ==== Returns
34
- # Whether or not the generator was created successfully
29
+ # @param name [String] the name to use for the new generator
30
+ # @option opt [String] :tool ('basic') the name of the tool to use
31
+ # @return [Boolean] was the generator successfully created?
35
32
  def self.create(name, opt={})
36
33
  return false unless Config.instance.project?
37
34
 
@@ -72,12 +69,9 @@ module Cog
72
69
  end
73
70
 
74
71
  # Run the generator with the given name
75
- #
76
- # ==== Arguments
77
- # * +name+ - the name of the generator
78
- #
79
- # ==== Returns
80
- # Whether or not the generator could be found
72
+ # @param name [String] name of the generator as returned by {Generator.list}
73
+ # @option opt [Boolean] :verbose (false) in the case of an exception, should a full stack trace be written?
74
+ # @return [Boolean] was the generator run successfully?
81
75
  def self.run(name, opt={})
82
76
  filename = File.join Cog::Config.instance.project_generators_path, "#{name}.rb"
83
77
  if File.exists? filename
@@ -92,17 +86,10 @@ module Cog
92
86
  false
93
87
  end
94
88
 
95
- # Get the template with the given name.
96
- #
97
- # ==== Parameters
98
- # * +path+ - a path to a template file which is relative to
99
- # one of the template directories
100
- #
101
- # ==== Options
102
- # * <tt>:absolute</tt> - is the +path+ argument absolute? (default: +false+)
103
- #
104
- # ==== Returns
105
- # An instance of ERB.
89
+ # Get the template with the given name
90
+ # @param path [String] path to template file relative one of the {Config#template_paths}
91
+ # @option opt [Boolean] :absolute (false) is the +path+ argument absolute?
92
+ # @return [ERB] an instance of {http://ruby-doc.org/stdlib-1.9.3/libdoc/erb/rdoc/ERB.html ERB}
106
93
  def get_template(path, opt={})
107
94
  path += '.erb'
108
95
  fullpath = if opt[:absolute]
@@ -117,19 +104,18 @@ module Cog
117
104
  ERB.new File.read(fullpath), 0, '>'
118
105
  end
119
106
 
120
- # Stamp a template +source+ onto a +destination+.
121
- #
122
- # ==== Arguments
123
- # * +template_path+ - a path to a template file which is relative to one
124
- # of the template directories
125
- # * +destination+ - a path to which the generated file should be written
126
- #
127
- # ==== Options
128
- # * <tt>:absolute_template_path</tt> - is the +template_path+ argument absolute? (default: +false+)
129
- # * <tt>:absolute_destination</tt> - is the +destination+ argument absolute? (default: +false+)
130
- def stamp(template_path, destination, opt={})
107
+ # Stamp a template into a file or return it as a string
108
+ # @param template_path [String] path to template file relative one of the {Config#template_paths}
109
+ # @param destination [String] path to which the generated file should be written, relative to the {Config#project_source_path}
110
+ # @option opt [Boolean] :absolute_template_path (false) is the +template_path+ absolute?
111
+ # @option opt [Boolean] :absolute_destination (false) is the +destination+ absolute?
112
+ # @option opt [Boolean] :quiet (false) suppress writing to STDOUT?
113
+ # @return [nil or String] if +destination+ is not provided, the stamped template is returned as a string
114
+ def stamp(template_path, destination=nil, opt={})
131
115
  t = get_template template_path, :absolute => opt[:absolute_template_path]
132
116
  b = opt[:binding] || binding
117
+ return t.result(b) if destination.nil?
118
+
133
119
  dest = opt[:absolute_destination] ? destination : File.join(Config.instance.project_source_path, destination)
134
120
  FileUtils.mkpath File.dirname(dest) unless File.exists? dest
135
121
  scratch = "#{dest}.scratch"
@@ -139,30 +125,38 @@ module Cog
139
125
  else
140
126
  updated = File.exists? dest
141
127
  FileUtils.mv scratch, dest
142
- STDOUT.write "#{updated ? :Updated : :Created} #{dest}\n".color(updated ? :white : :green)
128
+ STDOUT.write "#{updated ? :Updated : :Created} #{dest.relative_to_project_root}\n".color(updated ? :white : :green) unless opt[:quiet]
143
129
  end
144
130
  nil
145
131
  end
146
132
 
147
133
  # Copy a file from +src+ to +dest+, but only if +dest+ does not already exist.
148
- def copy_if_missing(src, dest)
134
+ # @param src [String] where to copy from
135
+ # @param dest [String] where to copy to
136
+ # @option opt [Boolean] :quiet (false) suppress writing to STDOUT?
137
+ # @return [nil]
138
+ def copy_if_missing(src, dest, opt={})
149
139
  unless File.exists? dest
150
140
  FileUtils.cp src, dest
151
- STDOUT.write "Created #{dest}\n".color(:green)
141
+ STDOUT.write "Created #{dest.relative_to_project_root}\n".color(:green) unless opt[:quiet]
152
142
  end
153
143
  end
154
144
 
155
145
  # Recursively create directories in the given path if they are missing.
156
- def touch_path(*path_components)
157
- path = File.join path_components
146
+ # @param path [String] a file system path representing a directory
147
+ # @option opt [Boolean] :quiet (false) suppress writing to STDOUT?
148
+ # @return [nil]
149
+ def touch_path(path, opt={})
158
150
  unless File.exists? path
159
151
  FileUtils.mkdir_p path
160
- STDOUT.write "Created #{path}\n".color(:green)
152
+ STDOUT.write "Created #{path.relative_to_project_root}\n".color(:green) unless opt[:quiet]
161
153
  end
154
+ nil
162
155
  end
163
156
 
164
157
  # File extension for a snippet of the given source code language.
165
- # ==== Example
158
+ # @api unstable
159
+ # @example
166
160
  # snippet_extension 'c++' # => 'h'
167
161
  def snippet_extension(lang = 'text') # :nodoc:
168
162
  case lang
@@ -172,24 +166,20 @@ module Cog
172
166
  'txt'
173
167
  end
174
168
  end
175
-
176
- # A warning that indicates a file is maintained by a generator
177
- def generated_warning # :nodoc:
178
- lang = Config.instance.language
179
- t = get_template "snippets/#{lang}/generated_warning.#{snippet_extension lang}", :cog_template => true
180
- t.result(binding)
181
- end
182
-
183
- def include_guard_begin(name) # :nodoc:
169
+
170
+ # @api unstable
171
+ def include_guard_begin(name)
184
172
  full = "COG_INCLUDE_GUARD_#{name.upcase}"
185
173
  "#ifndef #{full}\n#define #{full}"
186
174
  end
187
175
 
188
- def include_guard_end # :nodoc:
176
+ # @api unstable
177
+ def include_guard_end
189
178
  "#endif // COG_INCLUDE_GUARD_[...]"
190
179
  end
191
180
 
192
- def namespace_begin(name) # :nodoc:
181
+ # @api unstable
182
+ def namespace_begin(name)
193
183
  return if name.nil?
194
184
  case Config.instance.language
195
185
  when /c\+\+/
@@ -197,7 +187,8 @@ module Cog
197
187
  end
198
188
  end
199
189
 
200
- def namespace_end(name) # :nodoc:
190
+ # @api unstable
191
+ def namespace_end(name)
201
192
  return if name.nil?
202
193
  case Config.instance.language
203
194
  when /c\+\+/
@@ -206,7 +197,7 @@ module Cog
206
197
  end
207
198
 
208
199
  private
209
- def same?(original, scratch) # :nodoc:
200
+ def same?(original, scratch)
210
201
  if File.exists? original
211
202
  File.read(original) == File.read(scratch)
212
203
  else
@@ -0,0 +1 @@
1
+ require 'cog/helpers/string'
@@ -0,0 +1,11 @@
1
+ require 'cog/config'
2
+
3
+ class String
4
+
5
+ # @return [String] strips {Cog::Config#project_root} from the beginning of this string
6
+ def relative_to_project_root
7
+ return unless Cog::Config.instance.project?
8
+ root = Cog::Config.instance.project_root
9
+ start_with?(root) ? slice(root.length+1..-1) : dup
10
+ end
11
+ end
@@ -6,15 +6,17 @@ module Cog
6
6
 
7
7
  # Modules and classes to help write specs for testing +cog+
8
8
  #
9
- # === Example
10
- # Requiring the helpers will make extra SpecHelpers::Matchers available to
11
- # your RSpec tests. These are useful for testing a SpecHelpers::Invocation,
12
- # which is returned from a call to SpecHelpers::Runner#run
9
+ # Requiring the helpers will make extra {SpecHelpers::Matchers} available to
10
+ # your RSpec tests. These are useful for testing a {SpecHelpers::Invocation},
11
+ # which is returned from a call to {SpecHelpers::Runner#run}
13
12
  #
13
+ # @example
14
14
  # require 'cog/spec_helpers'
15
15
  #
16
16
  # describe 'The command line interface' do
17
17
  #
18
+ # include Cog::SpecHelpers
19
+ #
18
20
  # before :all do
19
21
  # @cog = Cog::SpecHelpers::Runner.new 'bin/cog'
20
22
  # end
@@ -22,42 +24,69 @@ module Cog
22
24
  # it 'should print help when no args are passed' do
23
25
  # @cog.run.should show_help
24
26
  # end
27
+ #
28
+ # context 'in an uninitialized project' do
29
+ #
30
+ # before :each do
31
+ # use_fixture :uninitialized
32
+ # end
25
33
  #
34
+ # it 'running `cog init` should make a Cogfile' do
35
+ # @cog.run(:init).should make(cogfile_path)
36
+ # end
37
+ #
38
+ # end
26
39
  # end
27
40
  module SpecHelpers
28
41
 
29
- # Absolute path to the root spec directory
42
+ # @return [String] absolute path to the root spec directory
30
43
  def spec_root
31
44
  File.expand_path File.join(File.dirname(__FILE__), '..', '..', 'spec')
32
45
  end
33
46
 
34
- # Directory of an active spec fixture.
47
+ # @return [String] directory of an active spec fixture.
35
48
  def active_fixture_dir
36
49
  File.join spec_root, 'active_fixture'
37
50
  end
38
51
 
39
- # Path to the Cogfile in the active spec fixture
52
+ # @return [String] path to the Cogfile in the active spec fixture
40
53
  def cogfile_path
41
54
  File.join active_fixture_dir, 'Cogfile'
42
55
  end
43
56
 
44
- # Path to the cog directory in the active spec fixture
57
+ # @return [String] path to the cog directory in the active spec fixture
45
58
  def cog_directory
46
59
  File.join active_fixture_dir, 'cog'
47
60
  end
48
61
 
49
- # Path to the generator with the given name
62
+ # @param name [String] active fixture generator identifier
63
+ # @return [String] path to the generator with the given name
50
64
  def generator(name)
51
65
  File.expand_path File.join(active_fixture_dir, 'cog', 'generators', "#{name}.rb")
52
66
  end
67
+
68
+ # @param name [String] template identifier (without the .erb extension)
69
+ # @return [String] absolute file system path to the template
70
+ def template(name)
71
+ File.expand_path File.join(active_fixture_dir, 'cog', 'templates', "#{name}")
72
+ end
53
73
 
54
- # Path to the test tool with the given name
74
+ # @param name [String] tool fixture identifier
75
+ # @return [String] path to the test tool with the given name
55
76
  def tool(name)
56
77
  File.expand_path File.join(spec_root, 'tools', name.to_s, 'lib', "#{name}.rb")
57
78
  end
58
79
 
59
- # The next cog spec will execute in a fresh copy of the given fixture directory.
80
+ # @param filename [String] name of a generated source file
81
+ # @return [String] absolute path to the generated file
82
+ def generated_file(filename)
83
+ File.expand_path File.join(active_fixture_dir, 'src', filename)
84
+ end
85
+
86
+ # The next cog spec will execute in a fresh copy of the given fixture
60
87
  # Fixture directories are stored in <tt>spec/fixtures</tt>.
88
+ # @param name [String] name of the fixture
89
+ # @return [nil]
61
90
  def use_fixture(name)
62
91
  path = File.join spec_root, 'fixtures', name.to_s
63
92
  if File.exists?(path) && File.directory?(path)
@@ -67,6 +96,7 @@ module Cog
67
96
  else
68
97
  throw :invalid_fixture_name
69
98
  end
99
+ nil
70
100
  end
71
101
 
72
102
  end
@@ -4,11 +4,12 @@ require 'rspec'
4
4
  module Cog
5
5
  module SpecHelpers
6
6
 
7
- # Extra should or should_not matchers for RSpec.
8
- # Check out #match_maker for help writing new matchers.
7
+ # Extra +should+ or +should_not+ matchers for RSpec.
8
+ # Check out {#match_maker} for help writing new matchers.
9
9
  module Matchers
10
10
 
11
- # The target Invocation should write something to STDERR, indicating an error
11
+ # The target {Invocation} should write something to STDERR, indicating an error
12
+ # @return [nil]
12
13
  def complain
13
14
  match_maker do
14
15
  message { "to [write something|not write anything] to STDERR" }
@@ -16,7 +17,9 @@ module Cog
16
17
  end
17
18
  end
18
19
 
19
- # The target Invocation should create a +Cogfile+ where none existed before
20
+ # The target {Invocation} should create a file at the given +path+
21
+ # @param path [String] path to check for a file after the invocation
22
+ # @return [nil]
20
23
  def make(path)
21
24
  match_maker do
22
25
  message { "to [create|not create] #{path}" }
@@ -29,7 +32,8 @@ module Cog
29
32
  end
30
33
  end
31
34
 
32
- # The target Invocation should do something, as determined by standard output
35
+ # The target {Invocation} should do something, as determined by standard output
36
+ # @return [nil]
33
37
  def do_something
34
38
  match_maker do
35
39
  message { "to [write something|not write anything] to STDOUT" }
@@ -37,7 +41,9 @@ module Cog
37
41
  end
38
42
  end
39
43
 
40
- # The target Invocation should write the given list of lines to standard output
44
+ # The target {Invocation} should write the given list of lines to standard output
45
+ # @param x [Array<String>] a list of lines to match against standard output
46
+ # @return [nil]
41
47
  def output(x)
42
48
  match_maker do
43
49
  message { "to [write|not write] #{x.join "\n"} to STDOUT"}
@@ -47,7 +53,8 @@ module Cog
47
53
  end
48
54
  end
49
55
 
50
- # The target Invocation should output the default help text
56
+ # The target {Invocation} should output the default help text
57
+ # @return [nil]
51
58
  def show_help
52
59
  match_maker do
53
60
  message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
@@ -2,8 +2,8 @@ module Cog
2
2
  module SpecHelpers
3
3
  module Matchers
4
4
 
5
- # Within Matchers#match_maker blocks, +self+ is set to an instance of this
6
- # class.
5
+ # Within {Matchers#match_maker} blocks, +self+ is set to an instance of this
6
+ # class
7
7
  class MatchMaker
8
8
 
9
9
  # A list of lines read from STDOUT after executing the Invocation
@@ -17,69 +17,91 @@ module Cog
17
17
  #
18
18
  # The template is used for both positive and negative failures.
19
19
  # Substrings which look like this <tt>"[positive|negative]</tt>" will
20
- # be replaced with the appropriate section. For example
20
+ # be replaced with the appropriate section.
21
+ #
22
+ # @example
21
23
  # message { "to [show|not show] the default help text" }
22
24
  #
23
25
  # would read "expected cog to show the default help text"
24
26
  # for a positive failure and "expected cog to not show the
25
27
  # default help text" for a negative failure. The "expected cog"
26
28
  # part is inserted automatically.
29
+ #
30
+ # @yield called after the invocation. {#lines} and {#error} can be used
31
+ # @return [nil]
27
32
  def message(&block)
28
33
  @msg_block = block
34
+ nil
29
35
  end
30
36
 
31
37
  # Define a block which runs before the Invocation.
32
38
  #
33
39
  # This is not required, but can be used to save context that is used
34
40
  # the in post invocation #test.
41
+ #
42
+ # @yield called before the invocation. Save context as instance variables
43
+ # @return [nil]
35
44
  def before(&block)
36
45
  @before_block = block
46
+ nil
37
47
  end
38
48
 
39
49
  # Define the test which runs after the Invocation
40
50
  #
41
51
  # This can make use of instance variables set during #before.
52
+ #
53
+ # @yield called after the invocation
54
+ # @return [nil]
42
55
  def test(&block)
43
56
  @test_block = block
57
+ nil
44
58
  end
45
59
 
46
- def matches?(runner) # :nodoc:
47
- @runner = runner
60
+ # @api developer
61
+ # @param invocation [Invocation] +cog+ executable and arguments bundled up
62
+ # @return [Boolean] result of the {#test} block
63
+ def matches?(invocation)
64
+ @invocation = invocation
48
65
  instance_eval &@before_block unless @before_block.nil?
49
- @runner.exec do |input, output, error|
66
+ @invocation.exec do |input, output, error|
50
67
  @lines = output.readlines
51
68
  @error = error.readlines
52
69
  end
53
70
  instance_eval &@test_block
54
71
  end
55
- def failure_message # :nodoc:
72
+
73
+ # @api developer
74
+ # @return [String] positive interpretation of the {#message} block result
75
+ def failure_message
56
76
  msg = instance_eval &@msg_block
57
77
  msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\1'
58
- "expected #{@runner} #{msg}\n#{trace}"
78
+ "expected #{@invocation} #{msg}\n#{trace}"
59
79
  end
60
- def negative_failure_message # :nodoc:
80
+
81
+ # @api developer
82
+ # @return [String] negative interpretation of the {#message} block result
83
+ def negative_failure_message
61
84
  msg = instance_eval &@msg_block
62
85
  msg = msg.gsub /\[([^\|\]]*)(?:\|([^\]]*)\])?/, '\2'
63
- "expected #{@runner} #{msg}\n#{trace}"
86
+ "expected #{@invocation} #{msg}\n#{trace}"
64
87
  end
65
88
 
66
- def trace # :nodoc
89
+ # @api developer
90
+ # @return [String] STDOUT and STDERR
91
+ def trace
67
92
  "STDOUT:\n#{@lines.join "\n"}\nSTDERR:\n#{@error.join "\n"}"
68
93
  end
69
94
  end
70
95
 
71
- # Makes it easy to write RSpec matchers
72
- #
73
- # Here is how the matcher for Matchers#show_help is written using this method
74
- # #match_maker method.
96
+ # Makes it easier to write RSpec matchers for testing +cog+ command invocations
97
+ # @yield +self+ is set to an instance of {MatchMaker}
98
+ # @example
75
99
  # def show_help
76
100
  # match_maker do
77
101
  # message { "to [show|not show] the default help text, got #{lines.first.inspect}" }
78
102
  # test { (/help.*code gen/ =~ lines[1]) }
79
103
  # end
80
104
  # end
81
- #
82
- # Within the +match_maker+ block, +self+ is set to an instance of MatchMaker.
83
105
  def match_maker(&block)
84
106
  m = MatchMaker.new
85
107
  m.instance_eval &block
@@ -9,16 +9,15 @@ module Cog
9
9
  # Value of the COG_TOOLS environment variable for invocations returned from #run
10
10
  attr_accessor :tools
11
11
 
12
+ # @param path_to_cl_app [String] path
12
13
  def initialize(path_to_cl_app)
13
14
  @cog = File.expand_path path_to_cl_app
14
15
  @tools = []
15
16
  end
16
17
 
17
18
  # Run cog with the given arguments
18
- #
19
- # === Returns
20
- # An instance of Invocation configured with the arguments. Use should and
21
- # should_not with the custom Matchers
19
+ # @param args [Array<String>] arguments to pass to +cog+
20
+ # @return [Invocation] an object which can be used with custom {Matchers}
22
21
  def run(*args)
23
22
  args = [@cog] + args
24
23
  Invocation.new(args.collect {|x| x.to_s}, :tools => @tools)
@@ -26,16 +25,23 @@ module Cog
26
25
  end
27
26
 
28
27
  # Represents a +cog+ command line invocation, which can be tested with
29
- # +RSpec+ +should+ and +should_not+ custom Matchers. This is the kind of
30
- # object returned by Runner#run.
28
+ # +RSpec+ +should+ and +should_not+ custom {Matchers}. This is the kind of
29
+ # object returned by {Runner#run}.
31
30
  class Invocation
32
31
 
33
- def initialize(cmd, opt={}) # :nodoc:
32
+ # @api developer
33
+ # @param cmd [Array<String>] path to +cog+ executable and arguments
34
+ # @option opt [Array<String>] :tools ([]) a list of tools to add to the +COG_TOOLS+ environment variable just before running the command with {#exec}
35
+ def initialize(cmd, opt={})
34
36
  @cmd = cmd
35
- @tools = opt[:tools].join ':'
37
+ @tools = (opt[:tools] || []).join ':'
36
38
  end
37
39
 
38
- def exec(*args, &block) # :nodoc:
40
+ # Execute the command
41
+ # @api developer
42
+ # @yield [stdin, stdout, stderr] standard pipes for the invocation
43
+ # @return [nil]
44
+ def exec(&block)
39
45
  @cmd = ['bundle', 'exec'] + @cmd
40
46
  ENV['COG_TOOLS'] = @tools
41
47
  Open3.popen3 *@cmd do |i,o,e,t|
@@ -43,7 +49,9 @@ module Cog
43
49
  end
44
50
  end
45
51
 
46
- def to_s # :nodoc:
52
+ # @api developer
53
+ # @return [String] loggable representation
54
+ def to_s
47
55
  "`COG_TOOLS=#{@tools} #{@cmd.compact.join ' '}`"
48
56
  end
49
57
  end
@@ -4,10 +4,12 @@ require 'rainbow'
4
4
 
5
5
  module Cog
6
6
 
7
- # For more details on writing tools see https://github.com/ktonon/cog#tools
7
+ # @see https://github.com/ktonon/cog#tools Introduction to Tools
8
8
  class Tool
9
9
 
10
10
  # A list of available tools
11
+ # @param verbose [Boolean] should full paths be listed for tools which are explicitly referenced?
12
+ # @return [Array<String>] a list of strings which can be passed to +require+
11
13
  def self.list(verbose=false)
12
14
  x = (ENV['COG_TOOLS'] || '').split ':'
13
15
  if x.all? {|path| path.slice(-3..-1) != '.rb' || File.exists?(path)}
@@ -29,9 +31,8 @@ module Cog
29
31
  end
30
32
 
31
33
  # Generate a new tool with the given name
32
- #
33
- # ==== Returns
34
- # Whether or not the generator was created successfully
34
+ # @param name [String] name of the tool to create. Should not conflict with other tool names
35
+ # @return [Boolean] was the tool created successfully?
35
36
  def self.create(name)
36
37
  if File.exists? name
37
38
  STDERR.write "A #{File.directory?(name) ? :directory : :file} named '#{name}' already exists\n".color(:red)
@@ -62,9 +63,8 @@ module Cog
62
63
  end
63
64
 
64
65
  # Find an available tool with the given name
65
- #
66
- # ==== Returns
67
- # A fully qualified tool path, which can be required
66
+ # @param name [String] name of the tool to search for
67
+ # @return [String] a fully qualified tool path, which can be passed to +require+
68
68
  def self.find(name)
69
69
  x = (ENV['COG_TOOLS'] || '').split ':'
70
70
  x.each do |path|
@@ -1,3 +1,5 @@
1
1
  module Cog
2
- VERSION = '0.0.19' unless const_defined? :VERSION
2
+ unless const_defined? :VERSION
3
+ VERSION = '0.0.20'
4
+ end
3
5
  end
@@ -0,0 +1,6 @@
1
+ #toc {
2
+ -webkit-box-shadow: 0px 0px 2px #bbb;
3
+ }
4
+ #search a:link, #search a:visited {
5
+ -webkit-box-shadow: 0px 0px 2px #eee;
6
+ }
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: 57
4
+ hash: 55
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 19
10
- version: 0.0.19
9
+ - 20
10
+ version: 0.0.20
11
11
  platform: ruby
12
12
  authors:
13
13
  - Kevin Tonon
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2012-11-05 00:00:00 Z
18
+ date: 2012-11-07 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: gli
@@ -60,7 +60,7 @@ dependencies:
60
60
  type: :development
61
61
  version_requirements: *id003
62
62
  - !ruby/object:Gem::Dependency
63
- name: rdoc
63
+ name: yard
64
64
  prerelease: false
65
65
  requirement: &id004 !ruby/object:Gem::Requirement
66
66
  none: false
@@ -79,16 +79,14 @@ executables:
79
79
  - cog
80
80
  extensions: []
81
81
 
82
- extra_rdoc_files:
83
- - API.rdoc
82
+ extra_rdoc_files: []
83
+
84
84
  files:
85
85
  - bin/cog
86
86
  - Default.cogfile
87
87
  - LICENSE
88
88
  - templates/cog/generator/basic-template.txt.erb.erb
89
89
  - templates/cog/generator/basic.rb.erb
90
- - templates/cog/snippets/c++/generated_warning.h.erb
91
- - templates/cog/snippets/generated_warning.txt
92
90
  - templates/cog/tool/API.rdoc.erb
93
91
  - templates/cog/tool/Gemfile.erb
94
92
  - templates/cog/tool/generator.rb.erb.erb
@@ -99,10 +97,13 @@ files:
99
97
  - templates/cog/tool/tool.gemspec.erb
100
98
  - templates/cog/tool/tool.rb.erb
101
99
  - templates/cog/tool/version.rb.erb
100
+ - templates/warning.h.erb
102
101
  - lib/cog/config/cogfile.rb
103
102
  - lib/cog/config.rb
104
103
  - lib/cog/errors.rb
105
104
  - lib/cog/generator.rb
105
+ - lib/cog/helpers/string.rb
106
+ - lib/cog/helpers.rb
106
107
  - lib/cog/spec_helpers/matchers/match_maker.rb
107
108
  - lib/cog/spec_helpers/matchers.rb
108
109
  - lib/cog/spec_helpers/runner.rb
@@ -110,17 +111,13 @@ files:
110
111
  - lib/cog/tool.rb
111
112
  - lib/cog/version.rb
112
113
  - lib/cog.rb
113
- - API.rdoc
114
+ - yard-templates/default/fulldoc/html/css/common.css
114
115
  homepage: https://github.com/ktonon/cog
115
116
  licenses: []
116
117
 
117
118
  post_install_message:
118
- rdoc_options:
119
- - --title
120
- - cog
121
- - --main
122
- - cog.rdoc
123
- - -ri
119
+ rdoc_options: []
120
+
124
121
  require_paths:
125
122
  - lib
126
123
  - lib
data/API.rdoc DELETED
@@ -1,6 +0,0 @@
1
- = cog API Docs
2
-
3
- +cog+ is a command line tool which helps you write code generators.
4
-
5
- This is the API docs. For a more general introduction to +cog+ visit
6
- https://github.com/ktonon/cog#readme
@@ -1,7 +0,0 @@
1
- WARNING
2
-
3
- This is a generated file. DO NOT EDIT THIS FILE! Your changes will be lost
4
- the next time this file is regenerated.
5
-
6
- This file was generating using cog
7
- https://github.com/ktonon/cog