gemma 0.0.2

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.
@@ -0,0 +1,150 @@
1
+ = gemma
2
+
3
+ http://github.com/jdleesmiller/gemma
4
+
5
+ == DESCRIPTION
6
+
7
+ If you are using .gemspecs as intended
8
+ (http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/), gemma generates
9
+ common rake tasks with default settings extracted from your .gemspec file.
10
+
11
+ == SYNOPSIS
12
+
13
+ To create a gem called +mygem+, first create <tt>mygem.gemspec</tt> as
14
+ described in http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/.
15
+
16
+ For more information about the gemspec, see the Gem::Specification Reference
17
+ (http://docs.rubygems.org/read/chapter/20).
18
+
19
+ Then put the following at the top of your <tt>Rakefile.rb</tt>:
20
+ begin
21
+ require 'rubygems'
22
+ require 'gemma'
23
+
24
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec'
25
+ rescue LoadError
26
+ # Gemma is not installed; print an (optional) message:
27
+ puts "Install gemma (sudo gem install gemma) for standard rake tasks."
28
+ end
29
+
30
+ This gives you a list of standard rake tasks with settings based on your
31
+ gemspec, in addition to any that you define yourself. (Note that the yard task
32
+ only appears if you have the yard gem installed.)
33
+
34
+ rake clean # Remove any temporary products.
35
+ rake clobber # Remove any generated file.
36
+ rake clobber_rcov # Remove rcov products for rcov
37
+ rake clobber_rdoc # Remove rdoc products
38
+ rake rcov # Analyze code coverage with tests
39
+ rake rdoc # Build the rdoc HTML Files
40
+ rake rerdoc # Force a rebuild of the RDOC files
41
+ rake test # Run tests
42
+ rake yard # Generate YARD Documentation
43
+
44
+ You can customize the generated tasks by passing a block to
45
+ +with_gemspec_file+:
46
+
47
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec' do |g|
48
+ g.rdoc.title = 'My Gem Is Great'
49
+ end
50
+
51
+ See the gemma API docs for more information.
52
+
53
+ == REQUIREMENTS
54
+
55
+ You must have ruby, rubygems and rake installed. Tasks are also included for
56
+ rcov (http://eigenclass.org/hiki.rb?rcov) and yard (http://yardoc.org/).
57
+
58
+ Gemma has been tested on:
59
+ * x86-linux (Ubuntu 10.04) with Ruby 1.8.7p249
60
+ * x86-linux (rvm) with Ruby 1.9.2p0 (2010-08-18 revision 29034)
61
+ * x86_64-linux (CentOS) with Ruby 1.8.7p72
62
+ * with yard 0.5.8 and 0.6.1
63
+ * with rcov 0.9.6 and 0.9.9
64
+ Gemma has not yet been tested on Windows.
65
+
66
+ == INSTALL
67
+
68
+ You should be able to install with
69
+
70
+ gem install gemma
71
+
72
+ Alternatively, you can get the source with
73
+
74
+ git clone git://github.com/jdleesmiller/gemma.git
75
+
76
+ and run
77
+
78
+ gem build gemma.gemspec
79
+ gem install gemma-<version>.gem
80
+
81
+ == RELATED PROJECTS
82
+
83
+ There are many projects that make gem development easier.
84
+ Hoe and Jeweler are the most popular; they generate the gemspec and tasks using
85
+ a configuration specified in the Rakefile, which is the opposite to what gemma
86
+ does. Mr Bones is a gem template generator that appears to be similar to Hoe
87
+ and Jeweler, but I haven't used it myself.
88
+
89
+ * http://seattlerb.rubyforge.org/hoe/
90
+ * http://github.com/technicalpickles/jeweler
91
+ * http://codeforpeople.rubyforge.org/bones/
92
+
93
+ gemesis provides tasks for building, releasing and installing gems based on the
94
+ gemspec, but (at the time of writing) it doesn't provide tasks for tests and
95
+ documentation, etc.
96
+
97
+ * http://github.com/markryall/gemesis/tree/master/lib/gemesis
98
+
99
+ rake-compiler provides support for compiling native extensions from a
100
+ gemspec, and it looks like it should work fairly well with gemma.
101
+
102
+ * http://github.com/luislavena/rake-compiler
103
+
104
+ Other helpful articles:
105
+
106
+ * http://rubygems.rubyforge.org/rubygems-update/Gem/Version.html
107
+ * http://jeffkreeftmeijer.com/2010/why-arent-you-using-git-flow/
108
+
109
+ == TODO
110
+
111
+ * make it easier to add custom tasks and / or new task generators, as in
112
+ # DOES NOT WORK YET
113
+ Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec' do |g|
114
+ g.yard_dev = Gemma::RakeTasks::YardTasks.new(g.gemspec, :yard_dev)
115
+ g.yard_dev.output = 'dev_docs'
116
+ g.yard_dev.options.push('--protected', '--private')
117
+ end
118
+ * more tasks (e.g. to publish docs)
119
+ * generate gem skeletons
120
+ * tasks for version control? (see http://github.com/nvie/gitflow)
121
+ * contributions welcome!
122
+
123
+ == HISTORY
124
+
125
+ <em>0.0.1</em>
126
+ * first release
127
+
128
+ == LICENSE
129
+
130
+ Copyright (c) 2010 John Lees-Miller
131
+
132
+ Permission is hereby granted, free of charge, to any person obtaining
133
+ a copy of this software and associated documentation files (the
134
+ 'Software'), to deal in the Software without restriction, including
135
+ without limitation the rights to use, copy, modify, merge, publish,
136
+ distribute, sublicense, and/or sell copies of the Software, and to
137
+ permit persons to whom the Software is furnished to do so, subject to
138
+ the following conditions:
139
+
140
+ The above copyright notice and this permission notice shall be
141
+ included in all copies or substantial portions of the Software.
142
+
143
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
144
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
145
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
146
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
147
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
148
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
149
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
150
+
@@ -0,0 +1,21 @@
1
+ require 'gemma/version'
2
+ require 'gemma/options'
3
+ require 'gemma/rake_tasks'
4
+
5
+ # Load default Rakefile plugins:
6
+ require 'gemma/rake_tasks/plugin'
7
+ require 'gemma/rake_tasks/gem_tasks'
8
+ require 'gemma/rake_tasks/rcov_tasks'
9
+ require 'gemma/rake_tasks/rdoc_tasks'
10
+ require 'gemma/rake_tasks/yard_tasks'
11
+ require 'gemma/rake_tasks/test_unit_tasks'
12
+
13
+ #require 'gemma/utility'
14
+
15
+ # Load default Rakefile plugins:
16
+ #require 'gemma/rakefile/rdoc'
17
+ #require 'gemma/rakefile/yard'
18
+ #require 'gemma/rakefile/test_unit'
19
+ #require 'gemma/rakefile/rcov'
20
+ #require 'gemma/rakefile/gem'
21
+
@@ -0,0 +1,97 @@
1
+ module Gemma
2
+ module Options
3
+ #
4
+ # @attr [String, nil] argument
5
+ # @attr [Array<String>] remaining_options
6
+ #
7
+ ExtractResult = Struct.new(:argument, :remaining_options)
8
+
9
+ #
10
+ # Extract the last option with one of the given `names` from `input`.
11
+ #
12
+ # Long form options of the form `--foo`, `--foo bar` and `--foo=bar` are
13
+ # supported (where `--foo` is the option name and `bar` is the argument in
14
+ # the last two forms).
15
+ #
16
+ # Short form options of the form `-f`, `-fbar` and `-f bar` are supported
17
+ # (where `-f` is the option name and `bar` is the argument in the last two
18
+ # forms). However concatenated short forms are not supported; that is, the
19
+ # option `-fg` is interpreted as `-f g` (option `f` with argument `g`)
20
+ # rather than `-f -g` (options `f` and `g` with no arguments).
21
+ #
22
+ # Abbreviated long form options (e.g. `--ex` for `--example`) are not
23
+ # supported, because this method doesn't know the full set of acceptable
24
+ # options, so it can't resolve ambiguities.
25
+ #
26
+ # If an option appears more than once, the argument for the last one is
27
+ # returned, and the previous matching options and arguments are deleted
28
+ # (i.e. not returned in {ExtractResult#remaining_options}).
29
+ #
30
+ # Matching options that appear after a `--` terminator are not extracted;
31
+ # they remain in the {ExtractResult#remaining_options} list.
32
+ #
33
+ # @example
34
+ # Gemma::Options.extract(%w(-a), %w(-a foo bar.txt))
35
+ # #=> #<struct Gemma::Options::ExtractResult argument="foo",
36
+ # # remaining_options=["bar.txt"]>
37
+ #
38
+ # @param [Array<String>] names one or more names for the option to extract
39
+ # (`['--file','-f']`, for example)
40
+ #
41
+ # @param [Array<String>] options to extract from; you should ensure that
42
+ # there isn't leading/trailing whitespace (strip), because this method
43
+ # doesn't detect it
44
+ #
45
+ # @return [ExtractResult] contains the argument for the given option and the
46
+ # rest of the options
47
+ #
48
+ def self.extract names, options
49
+ options = options.dup
50
+ result = nil
51
+ done = []
52
+
53
+ until options.empty?
54
+ x = options.shift
55
+ if x == '--' then
56
+ # Stop at the '--' terminator.
57
+ done << x
58
+ break
59
+ elsif x =~ /^(--[^=]+)/ then
60
+ if names.member?($1) then
61
+ # Found a long style option; look for its argument (if any).
62
+ if x =~ /=(.*)$/ then
63
+ result = $1
64
+ elsif !options.empty? && options.first !~ /^-./
65
+ result = options.shift
66
+ else
67
+ result = ''
68
+ end
69
+ else
70
+ done << x
71
+ end
72
+ elsif x =~ /^(-(.))(.*)/ then
73
+ # Found a short style option; this may actually represent several
74
+ # options; look for matching short options.
75
+ name, letter, rest = $1, $2, $3
76
+ if names.member?(name)
77
+ if rest.length > 0
78
+ result = rest
79
+ elsif !options.empty? && options.first !~ /^-./
80
+ result = options.shift
81
+ else
82
+ result = ''
83
+ end
84
+ else
85
+ done << x
86
+ end
87
+ else
88
+ # Not an option; just let it pass through.
89
+ done << x
90
+ end
91
+ end
92
+
93
+ ExtractResult.new(result, done + options)
94
+ end
95
+ end
96
+ end
97
+
@@ -0,0 +1,120 @@
1
+ require 'rake/clean'
2
+
3
+ module Gemma
4
+ #
5
+ # Generate standard gem development tasks; the tasks are configured using
6
+ # the settings in the given gemspec file.
7
+ #
8
+ # @example To create the default tasks based on your _mygem_.gemspec file:
9
+ # # At the top of Rakefile.rb.
10
+ # require 'rubygems'
11
+ # require 'gemma'
12
+ #
13
+ # Gemma::RakeTasks.with_gemspec_file 'mygem.gemspec'
14
+ #
15
+ # # ... other tasks ...
16
+ #
17
+ class RakeTasks
18
+
19
+ # Alias for new.
20
+ class <<self
21
+ alias :with_gemspec_file :new
22
+ end
23
+
24
+ #
25
+ # Constructor for internal use; you should usually use the
26
+ # `with_gemspec_file` alias (see examples in {RakeTasks}).
27
+ #
28
+ # @param [String, Gem::Specification] gemspec either the name of a gemspec
29
+ # file or a gemspec object; the latter is intended mainly for testing
30
+ #
31
+ # @yield [tasks] used to customize the tasks to be created
32
+ #
33
+ # @yieldparam [Gemma::RakeTasks] tasks self
34
+ #
35
+ # @private
36
+ #
37
+ def initialize gemspec, &block
38
+ # Load gemspec.
39
+ if gemspec.is_a?(String)
40
+ @gemspec_file_name = gemspec
41
+ @gemspec = Gem::Specification::load(gemspec_file_name)
42
+ elsif gemspec.is_a?(Gem::Specification)
43
+ @gemspec_file_name = nil
44
+ @gemspec = gemspec
45
+ else
46
+ raise ArgumentError
47
+ end
48
+
49
+ @plugins = {}
50
+ create_default_plugins
51
+
52
+ # Let the user add more plugins and alter settings.
53
+ block.call(self) if block_given?
54
+
55
+ @plugins.values.each do |plugin|
56
+ plugin.create_rake_tasks
57
+ end
58
+ end
59
+
60
+ #
61
+ # File from which the {#gemspec} was loaded.
62
+ #
63
+ # @return [String] not nil if a gemspec file name was passed to the
64
+ # constructor; otherwise, nil
65
+ #
66
+ attr_reader :gemspec_file_name
67
+
68
+ #
69
+ # The specification used to configure the rake tasks.
70
+ #
71
+ # @return [Gem::Specification] not nil; you should not modify this object
72
+ # (make the changes in the gemspec file instead).
73
+ #
74
+ attr_reader :gemspec
75
+
76
+ #
77
+ # @return [Hash<Symbol, Plugin>]
78
+ #
79
+ attr_reader :plugins
80
+
81
+ #
82
+ # @return [RcovTasks]
83
+ #
84
+ def rcov; @plugins[:rcov] end
85
+
86
+ #
87
+ # @return [RDocTasks]
88
+ #
89
+ def rdoc; @plugins[:rdoc] end
90
+
91
+ #
92
+ # @return [TestUnitTasks]
93
+ #
94
+ def test; @plugins[:test] end
95
+
96
+ #
97
+ # @return [YardTasks]
98
+ #
99
+ def yard; @plugins[:yard] end
100
+
101
+ #
102
+ # @return [GemTasks]
103
+ #
104
+ #def gem; @plugins[:gem] end
105
+
106
+ protected
107
+
108
+ def create_default_plugins
109
+ @plugins[:rcov] = Gemma::RakeTasks::RcovTasks.new(gemspec)
110
+ @plugins[:rdoc] = Gemma::RakeTasks::RDocTasks.new(gemspec)
111
+ @plugins[:test] = Gemma::RakeTasks::TestUnitTasks.new(gemspec)
112
+ @plugins[:yard] = Gemma::RakeTasks::YardTasks.new(gemspec)
113
+
114
+ # not that helpful yet
115
+ # @plugins[:gem] = Gemma::RakeTasks::GemTasks.new(gemspec,
116
+ # gemspec_file_name)
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,74 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to build and release (push) gems.
5
+ #
6
+ # TODO not done yet
7
+ #
8
+ class GemTasks < Plugin
9
+ #
10
+ # @param [Gem::Specification] gemspec
11
+ # @param [String, nil] gemspec_file_name
12
+ #
13
+ def initialize gemspec, gemspec_file_name
14
+ super(gemspec)
15
+
16
+ @gemspec_file_name = gemspec_file_name
17
+
18
+ # Defaults.
19
+ @output = 'pkg'
20
+ end
21
+
22
+ #
23
+ # Name of the gemspec file to be built; if this is nil, no gem tasks are
24
+ # generated.
25
+ #
26
+ # @return [String, nil]
27
+ #
28
+ attr_accessor :gemspec_file_name
29
+
30
+ #
31
+ # Name of directory in which gem files are placed; defaults to pkg.
32
+ #
33
+ # @return [String]
34
+ #
35
+ attr_accessor :output
36
+
37
+ #
38
+ # Full path to gem file.
39
+ #
40
+ # @return [String]
41
+ #
42
+ def gem_file
43
+ File.join(output, gemspec.file_name)
44
+ end
45
+
46
+ #
47
+ # Internal method; see {Plugin#create_rake_tasks}.
48
+ #
49
+ # @return [nil]
50
+ #
51
+ # @private
52
+ #
53
+ def create_rake_tasks
54
+ if gemspec_file_name
55
+ directory output
56
+
57
+ desc "gem build"
58
+ task :build => output do
59
+ sh "gem build #{gemspec_file_name}"
60
+ mv gemspec.file_name, gem_file
61
+ end
62
+ CLOBBER.include(gem_file)
63
+
64
+ desc "gem release"
65
+ task :release => :build do
66
+ sh "gem push #{gem_file}"
67
+ end
68
+ end
69
+
70
+ nil
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,36 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Plugins generate rake tasks based on the content of the gemspec.
5
+ #
6
+ # The intention is that the plugin processes the gemspec and sets
7
+ # (intelligent) default values when it is created. The {RakeTasks} object
8
+ # then calls {#create_rake_tasks} on every plugin that it knows about, after
9
+ # it has run its configuration block. The configuration block gives the
10
+ # caller a chance to customize the inputs to all of the plugins before they
11
+ # are generated.
12
+ #
13
+ class Plugin
14
+ def initialize gemspec
15
+ @gemspec = gemspec
16
+ end
17
+
18
+ #
19
+ # @return [Gem::Specification]
20
+ #
21
+ attr_reader :gemspec
22
+
23
+ #
24
+ # Internal method called by {RakeTasks} after the configuration block
25
+ # has executed; overriden by plugins to create rake tasks.
26
+ #
27
+ # @return [nil]
28
+ #
29
+ # @abstract
30
+ #
31
+ def create_rake_tasks
32
+ raise NotImplementedError
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,78 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to run test coverage using the built-in `rcov` tool. By
5
+ # default, the `test_files` given in the gemspec are used to measure
6
+ # coverage.
7
+ #
8
+ # This plugin is based on the `Rcov::RcovTask` that comes bundled with rcov.
9
+ # If you need an option that isn't exposed by the plugin, you can modify the
10
+ # `RcovTask` object directly in a block passed to {#with_rcov_task}.
11
+ #
12
+ class RcovTasks < Plugin
13
+ #
14
+ # @param [Gem::Specification] gemspec
15
+ #
16
+ def initialize gemspec
17
+ super(gemspec)
18
+
19
+ # Defaults.
20
+ @task_name = :rcov
21
+ @output = 'rcov'
22
+ @with_rcov_task = nil
23
+ end
24
+
25
+ #
26
+ # Name of rake task; defaults to rcov.
27
+ #
28
+ # @return [Symbol]
29
+ #
30
+ attr_accessor :task_name
31
+
32
+ #
33
+ # Output directory for the XHTML report; defaults to rcov.
34
+ #
35
+ # @return [String]
36
+ #
37
+ attr_accessor :output
38
+
39
+ #
40
+ # Customize the rcov task.
41
+ #
42
+ # @yield [rcov] called after the defaults are set but before the rcov task
43
+ # is generated
44
+ #
45
+ # @yieldparam [Rcov::RcovTask] rcov
46
+ #
47
+ # @return [nil]
48
+ #
49
+ def with_rcov_task &block
50
+ @with_rcov_task = block
51
+ nil
52
+ end
53
+
54
+ #
55
+ # Internal method; see {Plugin#create_rake_tasks}.
56
+ #
57
+ # @return [nil]
58
+ #
59
+ # @private
60
+ #
61
+ def create_rake_tasks
62
+ begin
63
+ require 'rcov/rcovtask'
64
+ Rcov::RcovTask.new(self.task_name) do |rcov|
65
+ rcov.libs = gemspec.require_paths
66
+ rcov.test_files = gemspec.test_files
67
+ rcov.warning = true
68
+ rcov.rcov_opts << "-x ^/"
69
+ rcov.output_dir = self.output
70
+ @with_rcov_task.call(rcov) if @with_rcov_task
71
+ end
72
+ rescue LoadError
73
+ # Assume rcov is not installed.
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,159 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks for generating `rdoc` API documentation with settings from
5
+ # the gemspec.
6
+ #
7
+ # The default settings are based on the `files`, `rdoc_options` and
8
+ # `extra_rdoc_files` data in the gemspec. By default, test cases (which
9
+ # might be included in `files`) are not documented.
10
+ #
11
+ # If an rdoc gem is installed, it will be used; otherwise, the built-in
12
+ # rdoc will be used.
13
+ #
14
+ # This plugin is based on the `Rake::RDocTask` that comes bundled with rake.
15
+ # If you need an option that isn't exposed by the plugin, you can modify the
16
+ # `RDocTask` object directly in a block passed to {#with_rdoc_task}.
17
+ #
18
+ class RDocTasks < Plugin
19
+ #
20
+ # @param [Gem::Specification] gemspec
21
+ #
22
+ def initialize gemspec
23
+ super(gemspec)
24
+
25
+ # Defaults.
26
+ @use_gem_if_available = true
27
+ @task_name = :rdoc
28
+ @with_rdoc_task = nil
29
+
30
+ # I'm not sure whether it's a good idea to pass -o in the gemspec, but
31
+ # for now we'll handle it, because it's needed in the Rakefile.
32
+ @options = gemspec.rdoc_options
33
+ @output, @options = Options.extract(%w(-o --output --op), @options).to_a
34
+ @output ||= 'rdoc'
35
+
36
+ # Extract --main, --title and --template so RDocTask can have them.
37
+ @main, @options = Options.extract(%w(-m --main), @options).to_a
38
+ @title, @options = Options.extract(%w(-t --title), @options).to_a
39
+ @template, @options = Options.extract(%w(-T --template), @options).to_a
40
+
41
+ # Don't include the test files by default.
42
+ @files = gemspec.files - gemspec.test_files
43
+ end
44
+
45
+ #
46
+ # Name of rake task used to generate these docs; defaults to rdoc.
47
+ #
48
+ # @return [Symbol]
49
+ #
50
+ attr_accessor :task_name
51
+
52
+ #
53
+ # Name of output directory (the rdoc option --output); extracted from
54
+ # gemspec; defaults to rdoc.
55
+ #
56
+ # @return [String]
57
+ #
58
+ attr_accessor :output
59
+
60
+ #
61
+ # Name of file to display in index.html (the rdoc option --main);
62
+ # extracted from gemspec; defaults to nil (none).
63
+ #
64
+ # @return [String, nil]
65
+ #
66
+ attr_accessor :main
67
+
68
+ #
69
+ # Title for HTML output (the rdoc option --title); extracted from gemspec;
70
+ # defaults to nil (unspecified).
71
+ #
72
+ # @return [String, nil]
73
+ #
74
+ attr_accessor :title
75
+
76
+ #
77
+ # Name of template used to generate html output (the rdoc option
78
+ # --template); extracted from gemspec; defaults to nil (unspecified).
79
+ #
80
+ # @return [String, nil]
81
+ #
82
+ attr_accessor :template
83
+
84
+ #
85
+ # If an rdoc gem is installed, use it instead of the rdoc from the
86
+ # standard library (default true).
87
+ #
88
+ # While rdoc is part of the ruby standard library, newer versions are
89
+ # available as gems.
90
+ #
91
+ # @return [Boolean]
92
+ #
93
+ attr_accessor :use_gem_if_available
94
+
95
+ #
96
+ # Files to be processed by rdoc; extracted from gemspec; test files are
97
+ # not included by default.
98
+ #
99
+ # @return [Array<String>]
100
+ #
101
+ attr_accessor :files
102
+
103
+ #
104
+ # Options to be passed to rdoc; extracted from gemspec; note that
105
+ # the {#output}, {#main}, {#title} and {#template} options and the
106
+ # {#files} list are handled separately.
107
+ #
108
+ # @return [Array<String>]
109
+ #
110
+ attr_accessor :options
111
+
112
+ #
113
+ # Customize the rdoc task.
114
+ #
115
+ # @yield [rd] called after the defaults are set but before the rdoc tasks
116
+ # are generated
117
+ #
118
+ # @yieldparam [Rake::RDocTask] rd
119
+ #
120
+ # @return [nil]
121
+ #
122
+ def with_rdoc_task &block
123
+ @with_rdoc_task = block
124
+ nil
125
+ end
126
+
127
+ #
128
+ # Internal method; see {Plugin#create_rake_tasks}.
129
+ #
130
+ # @return [nil]
131
+ #
132
+ # @private
133
+ #
134
+ def create_rake_tasks
135
+ if use_gem_if_available
136
+ begin
137
+ gem('rdoc')
138
+ rescue LoadError
139
+ # ignore -- just use the standard library one
140
+ end
141
+ end
142
+
143
+ require 'rake/rdoctask'
144
+ Rake::RDocTask.new(self.task_name) do |rd|
145
+ rd.rdoc_dir = self.output
146
+ rd.rdoc_files = self.files
147
+ rd.title = self.title
148
+ rd.main = self.main
149
+ rd.template = self.template
150
+ rd.options = self.options
151
+ rd.inline_source = false # doesn't seem to work on 1.8.7
152
+ @with_rdoc_task.call(rd) if @with_rdoc_task
153
+ end
154
+
155
+ nil
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,64 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to run Test::Unit tests using the built-in (standard library)
5
+ # `test/unit`. By default, the `test_files` given in the gemspec are tested.
6
+ #
7
+ # This plugin is based on the `Rake::TestTask` that comes bundled with rake.
8
+ # If you need an option that isn't exposed by the plugin, you can modify the
9
+ # `TestTask` object directly in a block passed to {#with_test_task}.
10
+ #
11
+ class TestUnitTasks < Plugin
12
+ #
13
+ # @param [Gem::Specification] gemspec
14
+ #
15
+ def initialize gemspec
16
+ super(gemspec)
17
+
18
+ # Defaults.
19
+ @task_name = :test
20
+ @with_test_task = nil
21
+ end
22
+
23
+ #
24
+ # Name of rake task used to generate these docs; defaults to test.
25
+ #
26
+ # @return [Symbol]
27
+ #
28
+ attr_accessor :task_name
29
+
30
+ #
31
+ # Customize the test task.
32
+ #
33
+ # @yield [tt] called after the defaults are set but before the test task
34
+ # is generated
35
+ #
36
+ # @yieldparam [Rake::TestTask] tt
37
+ #
38
+ # @return [nil]
39
+ #
40
+ def with_test_task &block
41
+ @with_test_task = block
42
+ nil
43
+ end
44
+
45
+ #
46
+ # Internal method; see {Plugin#create_rake_tasks}.
47
+ #
48
+ # @return [nil]
49
+ #
50
+ # @private
51
+ #
52
+ def create_rake_tasks
53
+ require 'rake/testtask'
54
+ Rake::TestTask.new(self.task_name) do |tt|
55
+ tt.libs = gemspec.require_paths
56
+ tt.test_files = gemspec.test_files
57
+ tt.warning = true
58
+ @with_test_task.call(tt) if @with_test_task
59
+ end
60
+ nil
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,165 @@
1
+ module Gemma
2
+ class RakeTasks
3
+ #
4
+ # Create tasks to generate documentation with yard (yardoc) if it is
5
+ # available.
6
+ #
7
+ # The files to document are extracted from the gemspec's `files` and
8
+ # `extra_rdoc_files` members.
9
+ #
10
+ # Unfortunately, yardoc's command line options are largely incompatible with
11
+ # those for rdoc, but the `--main` and `--title` options from `rdoc_options`
12
+ # are also passed through to yardoc by default. The short forms `-m` and
13
+ # `-t` of these arguments are also passed on as `--main` and `--title` to
14
+ # yardoc (note that `-m` and `-t` mean different things to yardoc than to
15
+ # rdoc!). Note that any files (that is, non-options) in `rdoc_options` are
16
+ # also ignored.
17
+ #
18
+ # If you want to further customize your yardoc output, you can add options
19
+ # in the {Gemma::RakeTasks.with_gemspec_file} configuration block.
20
+ #
21
+ # This plugin is based on the `YARD::Rake::YardocTask` that comes bundled
22
+ # with yard. If you need an option that isn't exposed by the plugin, you
23
+ # can modify the `YardocTask` object directly in a block passed to
24
+ # {#with_yardoc_task}.
25
+ #
26
+ class YardTasks < Plugin
27
+ #
28
+ # @param [Gem::Specification] gemspec
29
+ #
30
+ def initialize gemspec
31
+ super(gemspec)
32
+
33
+ # Defaults.
34
+ @task_name = :yard
35
+ @output = 'yard'
36
+ @with_yardoc_task = nil
37
+
38
+ # Extract supported rdoc options and add to the default yard options.
39
+ # Keep track of main, if it is given, because we have to remove it from
40
+ # the extra files list (otherwise it shows up twice in the output).
41
+ @main = Options.extract(%w(-m --main), gemspec.rdoc_options).argument
42
+ @title = Options.extract(%w(-t --title), gemspec.rdoc_options).argument
43
+
44
+ @options = []
45
+
46
+ # Don't document the test files.
47
+ # Yard splits up the ruby files from the 'extra' files.
48
+ @files = gemspec.files - gemspec.test_files - gemspec.extra_rdoc_files
49
+ @extra_files = gemspec.extra_rdoc_files.dup
50
+ @extra_files.delete(main) if main
51
+ end
52
+
53
+ #
54
+ # Name of rake task used to generate these docs; defaults to yard.
55
+ #
56
+ # @return [Symbol]
57
+ #
58
+ attr_accessor :task_name
59
+
60
+ #
61
+ # Name of output directory (the yard option --output); defaults to yard.
62
+ #
63
+ # @return [String]
64
+ #
65
+ attr_accessor :output
66
+
67
+ #
68
+ # Name of file to display in index.html (the yard option --main);
69
+ # extracted from gemspec; defaults to nil (none).
70
+ #
71
+ # @return [String, nil]
72
+ #
73
+ attr_accessor :main
74
+
75
+ #
76
+ # Title for HTML output (the yard option --title); extracted from gemspec;
77
+ # defaults to nil (unspecified).
78
+ #
79
+ # @return [String, nil]
80
+ #
81
+ attr_accessor :title
82
+
83
+ #
84
+ # Ruby files to be processed by yard; these are extracted from the
85
+ # gemspec; test files are not included by default.
86
+ #
87
+ # @return [Array<String>]
88
+ #
89
+ attr_accessor :files
90
+
91
+ #
92
+ # Extra files (e.g. FAQ, LICENSE) to be processed by yard; these are
93
+ # extracted from the gemspec.
94
+ #
95
+ # @return [Array<String>]
96
+ #
97
+ attr_accessor :extra_files
98
+
99
+ #
100
+ # Options to be passed to yard; note that the {#output} option and the
101
+ # {#files} and {#extra_files} lists are handled separately.
102
+ #
103
+ # @return [Array<String>]
104
+ #
105
+ attr_accessor :options
106
+
107
+ #
108
+ # Customize the yardoc task (e.g. to add blocks to run before or after the
109
+ # docs are generated).
110
+ #
111
+ # @yield [yd] called after the defaults are set but before the yard task
112
+ # is generated
113
+ #
114
+ # @yieldparam [YARD::Rake::YardocTask] yd
115
+ #
116
+ # @return [nil]
117
+ #
118
+ def with_yardoc_task &block
119
+ @with_yardoc_task = block
120
+ nil
121
+ end
122
+
123
+ #
124
+ # Internal method; see {Plugin#create_rake_tasks}.
125
+ #
126
+ # @return [nil]
127
+ #
128
+ # @private
129
+ #
130
+ def create_rake_tasks
131
+ begin
132
+ require 'yard'
133
+ YARD::Rake::YardocTask.new do |yd|
134
+ yd.name = self.task_name
135
+ yd.options = complete_options
136
+ yd.files = self.files
137
+ yd.files.push('-', *self.extra_files) unless self.extra_files.empty?
138
+ @with_yardoc_task.call(yd) if @with_yardoc_task
139
+ end
140
+ CLOBBER.include(self.output)
141
+ CLOBBER.include('.yardoc')
142
+ rescue LoadError
143
+ # Assume yard is not installed.
144
+ end
145
+ nil
146
+ end
147
+
148
+ private
149
+
150
+ #
151
+ # Options to be passed to yardoc; this includes {#options} and the
152
+ # {#main}, {#title} and {#output} options.
153
+ #
154
+ # @return [Array<String>]
155
+ #
156
+ def complete_options
157
+ opts = self.options.dup
158
+ opts.push('--main', self.main) if self.main
159
+ opts.push('--title', self.title) if self.title
160
+ opts.push('--output', self.output)
161
+ opts
162
+ end
163
+ end
164
+ end
165
+ end
@@ -0,0 +1,3 @@
1
+ module Gemma
2
+ VERSION = '0.0.2'
3
+ end
@@ -0,0 +1,137 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "gemma"
4
+ require "set"
5
+
6
+ class TestGemma < Test::Unit::TestCase
7
+ def test_empty_spec
8
+ s = Gem::Specification.new
9
+ Gemma::RakeTasks.new(s)
10
+ end
11
+
12
+ def test_rdoc
13
+ s = Gem::Specification.new
14
+ s.files = %w(lib/a.rb lib/b.rb)
15
+ s.test_files = %w(test/test_a.rb test/test_a.rb)
16
+ s.rdoc_options = ['--main', 'README.md']
17
+ s.extra_rdoc_files = ['README.md', 'FAQ']
18
+
19
+ Gemma::RakeTasks.new(s) do |g|
20
+ assert_equal %w(lib/a.rb lib/b.rb README.md FAQ).to_set,
21
+ g.rdoc.files.to_set
22
+ assert_equal [], g.rdoc.options
23
+ assert_equal 'README.md', g.rdoc.main
24
+ assert_equal nil, g.rdoc.title
25
+
26
+ g.rdoc.with_rdoc_task do |rd|
27
+ assert_equal rd.rdoc_files, g.rdoc.files
28
+ end
29
+ end
30
+ end
31
+
32
+ def test_yard
33
+ s = Gem::Specification.new
34
+ s.files = %w(lib/a.rb)
35
+ s.test_files = %w(test/test_a.rb)
36
+ s.rdoc_options = ['--main', 'README.rdoc']
37
+ s.extra_rdoc_files = ['README.rdoc']
38
+
39
+ # Just one option.
40
+ # A file should not be passed as an extra file if it's the --main file.
41
+ # Test files should not be documented.
42
+ Gemma::RakeTasks.new(s) do |g|
43
+ assert_equal %w(lib/a.rb), g.yard.files
44
+ assert_equal [], g.yard.extra_files
45
+ assert_equal 'README.rdoc', g.yard.main
46
+ assert_equal [], g.yard.options
47
+ assert_equal 'yard', g.yard.output
48
+ assert_equal :yard, g.yard.task_name
49
+ assert_equal nil, g.yard.title
50
+
51
+ g.yard.with_yardoc_task do |yd|
52
+ assert_equal %w(lib/a.rb), yd.files
53
+ assert_equal 4, yd.options.size
54
+ assert_equal 'README.rdoc',
55
+ Gemma::Options.extract(%w(--main), yd.options).argument
56
+ assert_equal 'yard',
57
+ Gemma::Options.extract(%w(--output), yd.options).argument
58
+ end
59
+ end
60
+
61
+ # Add some extra files (that aren't the --main file).
62
+ s.extra_rdoc_files << 'FAQ'
63
+ Gemma::RakeTasks.new(s) do |g|
64
+ assert_equal %w(lib/a.rb), g.yard.files
65
+ assert_equal %w(FAQ), g.yard.extra_files
66
+ assert_equal 'README.rdoc', g.yard.main
67
+ assert_equal [], g.yard.options
68
+ end
69
+
70
+ # Make sure extra options are ignored.
71
+ s.rdoc_options = ['--main', 'README.rdoc', '--diagram']
72
+ Gemma::RakeTasks.new(s) do |g|
73
+ assert_equal %w(lib/a.rb), g.yard.files
74
+ assert_equal %w(FAQ), g.yard.extra_files
75
+ assert_equal 'README.rdoc', g.yard.main
76
+ assert_equal [], g.yard.options
77
+ end
78
+ s.rdoc_options = ['--diagram', '--main', 'README.rdoc']
79
+ Gemma::RakeTasks.new(s) do |g|
80
+ assert_equal %w(lib/a.rb), g.yard.files
81
+ assert_equal %w(FAQ), g.yard.extra_files
82
+ assert_equal 'README.rdoc', g.yard.main
83
+ assert_equal [], g.yard.options
84
+ end
85
+
86
+ # Some more complicated options.
87
+ # Note that we ignore things that could be files ('bat').
88
+ s.rdoc_options = ['foo bar', '--baz', 'bat', '--title', 'a b c',
89
+ '--diagram', '--main', 'README.rdoc', 'ABCD']
90
+ Gemma::RakeTasks.new(s) do |g|
91
+ assert_equal 'a b c', g.yard.title
92
+ assert_equal [], g.yard.options
93
+
94
+ g.yard.with_yardoc_task do |yd|
95
+ assert_equal %w(lib/a.rb - FAQ), yd.files
96
+ assert_equal 6, yd.options.size
97
+ assert_equal 'README.rdoc',
98
+ Gemma::Options.extract(%w(--main), yd.options).argument
99
+ assert_equal 'yard',
100
+ Gemma::Options.extract(%w(--output), yd.options).argument
101
+ assert_equal 'a b c',
102
+ Gemma::Options.extract(%w(--title), yd.options).argument
103
+ end
104
+ end
105
+ end
106
+
107
+ def test_test_unit
108
+ s = Gem::Specification.new
109
+ s.files = %w(lib/a.rb lib/b.rb)
110
+ s.test_files = %w(test/test_a.rb test/test_b.rb)
111
+ s.require_paths << 'ext'
112
+
113
+ Gemma::RakeTasks.new(s) do |g|
114
+ g.test.with_test_task do |tt|
115
+ assert_equal %w(lib ext).to_set, tt.libs.to_set
116
+ assert_equal %w(test/test_a.rb test/test_b.rb).to_set,
117
+ tt.file_list.to_a.to_set
118
+ end
119
+ end
120
+ end
121
+
122
+ def test_rcov
123
+ s = Gem::Specification.new
124
+ s.files = %w(lib/a.rb lib/b.rb)
125
+ s.test_files = %w(test/test_a.rb test/test_b.rb)
126
+ s.require_paths << 'ext'
127
+
128
+ Gemma::RakeTasks.new(s) do |g|
129
+ g.rcov.with_rcov_task do |rcov|
130
+ assert_equal %w(lib ext).to_set, rcov.libs.to_set
131
+ assert_equal %w(test/test_a.rb test/test_b.rb).to_set,
132
+ rcov.file_list.to_a.to_set
133
+ end
134
+ end
135
+ end
136
+ end
137
+
@@ -0,0 +1,101 @@
1
+ require "test/unit"
2
+ require "rubygems"
3
+ require "gemma"
4
+
5
+ class TestOptions < Test::Unit::TestCase
6
+ include Gemma
7
+
8
+ def test_empty
9
+ # empty input
10
+ assert_equal Options::ExtractResult.new(nil, []),
11
+ Options.extract(%w(--a), [])
12
+ end
13
+
14
+ def test_long_form
15
+ input = %w(--a av --b --c=cv)
16
+
17
+ # option a has an argument
18
+ assert_equal Options::ExtractResult.new('av', %w(--b --c=cv)),
19
+ Options.extract(%w(--a), input)
20
+
21
+ # option b has no argument; result is ''
22
+ assert_equal Options::ExtractResult.new('', %w(--a av --c=cv)),
23
+ Options.extract(%w(--b), input)
24
+
25
+ # option c also has argument
26
+ assert_equal Options::ExtractResult.new('cv', %w(--a av --b)),
27
+ Options.extract(%w(--c), input)
28
+
29
+ # there is no option d; result is nil
30
+ assert_equal Options::ExtractResult.new(nil, input),
31
+ Options.extract(%w(--d), input)
32
+ end
33
+
34
+ def test_terminator
35
+ # just the -- terminator
36
+ assert_equal Options::ExtractResult.new(nil, ['--']),
37
+ Options.extract(%w(--a), ['--'])
38
+
39
+ # should keep content before and after the -- terminator
40
+ assert_equal Options::ExtractResult.new(nil, %w(a -- b)),
41
+ Options.extract(%w(--a), %w(a -- b))
42
+ end
43
+
44
+ def test_terminator_2
45
+ input = %w(foo --a av -- --b bv)
46
+
47
+ # should not be able to find options after the -- terminator
48
+ assert_equal Options::ExtractResult.new('av', %w(foo -- --b bv)),
49
+ Options.extract(%w(--a), input)
50
+ assert_equal Options::ExtractResult.new(nil, input),
51
+ Options.extract(%w(--b), input)
52
+ assert_equal Options::ExtractResult.new('', %w(-- --b)),
53
+ Options.extract(%w(--a), %w(--a -- --b))
54
+ assert_equal Options::ExtractResult.new(nil, %w(--a -- --b)),
55
+ Options.extract(%w(--b), %w(--a -- --b))
56
+ end
57
+
58
+ def test_short_form
59
+ # should be able to find -a but not -b
60
+ input = %w(foo -a av -- -b bv)
61
+ assert_equal Options::ExtractResult.new('av', %w(foo -- -b bv)),
62
+ Options.extract(%w(-a), input)
63
+ assert_equal Options::ExtractResult.new(nil, input),
64
+ Options.extract(%w(-b), input)
65
+
66
+ # the -aav and -b bv forms
67
+ input = %w(-aav -b bv)
68
+ assert_equal Options::ExtractResult.new('av', %w(-b bv)),
69
+ Options.extract(%w(-a), input)
70
+ assert_equal Options::ExtractResult.new('bv', %w(-aav)),
71
+ Options.extract(%w(-b), input)
72
+
73
+ # short form with no argument
74
+ assert_equal Options::ExtractResult.new('', %w(-a av)),
75
+ Options.extract(%w(-b), %w(-a av -b))
76
+
77
+ # missing short form argument
78
+ assert_equal Options::ExtractResult.new(nil, %w(-a av -b foo bar.txt)),
79
+ Options.extract(%w(-c), %w(-a av -b foo bar.txt))
80
+ end
81
+
82
+ def test_multiple_options
83
+ # single -a means we pick up a1
84
+ assert_equal Options::ExtractResult.new('a1', []),
85
+ Options.extract(%w(-a), %w(-a a1))
86
+
87
+ # the second -a means that we pick up a2
88
+ assert_equal Options::ExtractResult.new('a2', []),
89
+ Options.extract(%w(-a), %w(-a a1 -a a2))
90
+ assert_equal Options::ExtractResult.new('a2', %w(hi -bfoo)),
91
+ Options.extract(%w(-a), %w(hi -a a1 -a a2 -bfoo))
92
+
93
+ # mixing long and short forms doesn't affect this
94
+ assert_equal Options::ExtractResult.new('a2', []),
95
+ Options.extract(%w(-a --a), %w(-a a1 --a a2))
96
+
97
+ # a duplicate option after the -- terminator makes no difference
98
+ assert_equal Options::ExtractResult.new('a1', %w(-- -aa2)),
99
+ Options.extract(%w(-a), %w(-a a1 -- -aa2))
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,86 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gemma
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 2
10
+ version: 0.0.2
11
+ platform: ruby
12
+ authors:
13
+ - John Lees-Miller
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-09-20 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description: |
23
+ If you are using .gemspecs as intended
24
+ (http://yehudakatz.com/2010/04/02/using-gemspecs-as-intended/), gemma generates
25
+ common rake tasks with default settings extracted from your .gemspec file.
26
+
27
+ email:
28
+ - jdleesmiller@gmail.com
29
+ executables: []
30
+
31
+ extensions: []
32
+
33
+ extra_rdoc_files:
34
+ - README.rdoc
35
+ files:
36
+ - lib/gemma/rake_tasks/gem_tasks.rb
37
+ - lib/gemma/rake_tasks/rcov_tasks.rb
38
+ - lib/gemma/rake_tasks/yard_tasks.rb
39
+ - lib/gemma/rake_tasks/rdoc_tasks.rb
40
+ - lib/gemma/rake_tasks/test_unit_tasks.rb
41
+ - lib/gemma/rake_tasks/plugin.rb
42
+ - lib/gemma/options.rb
43
+ - lib/gemma/rake_tasks.rb
44
+ - lib/gemma/version.rb
45
+ - lib/gemma.rb
46
+ - README.rdoc
47
+ - test/test_options.rb
48
+ - test/test_gemma.rb
49
+ has_rdoc: true
50
+ homepage: http://github.com/jdleesmiller/gemma
51
+ licenses: []
52
+
53
+ post_install_message:
54
+ rdoc_options:
55
+ - --main
56
+ - README.rdoc
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ hash: 3
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ hash: 3
74
+ segments:
75
+ - 0
76
+ version: "0"
77
+ requirements: []
78
+
79
+ rubyforge_project:
80
+ rubygems_version: 1.3.7
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Generate helpful rake tasks from your gemspec.
84
+ test_files:
85
+ - test/test_options.rb
86
+ - test/test_gemma.rb