cli-forge 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ coverage/
2
+ tmp/
3
+ .DS_Store
4
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --order random
4
+ --require spec_helper
@@ -0,0 +1,3 @@
1
+ SimpleCov.start do
2
+ add_filter "/spec/"
3
+ end
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ bundler_args: --without debugging development
3
+ script: bundle exec rake spec:ci
4
+ rvm:
5
+ - 1.8.7
6
+ - 1.9.2
7
+ - 1.9.3
8
+ - 2.0.0
9
+ - rbx-18mode
10
+ - rbx-19mode
11
+ - jruby-18mode
12
+ - jruby-19mode
13
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,61 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ # No gem would be complete without rake tasks - http://rake.rubyforge.org/
6
+ # MIT License - http://rake.rubyforge.org/files/MIT-LICENSE.html
7
+ gem "rake", "~> 10.0"
8
+
9
+ group :test do
10
+ # Our preferred unit testing library - https://www.relishapp.com/rspec
11
+ # MIT License - https://github.com/rspec/rspec/blob/master/License.txt
12
+ gem "rspec", "~> 2.13"
13
+
14
+ # The preferred code mutation library.
15
+ # MIT License - https://github.com/mbj/mutant/blob/master/LICENSE
16
+ gem "mutant", ">= 0.2.20", "< 1.0.0", :platforms => :ruby_19
17
+
18
+ # Cover all the things - https://github.com/colszowka/simplecov
19
+ # MIT License - https://github.com/colszowka/simplecov/blob/master/LICENSE
20
+ gem "simplecov", "~> 0.7"
21
+
22
+ # Code coverage in badge form - https://coveralls.io/
23
+ # MIT License - https://github.com/lemurheavy/coveralls-ruby/blob/master/LICENSE
24
+ gem "coveralls", "~> 0.6"
25
+ end
26
+
27
+ group :debugging do
28
+ # A REPL like IRB, but much better - http://pryrepl.org/
29
+ # MIT License - https://github.com/pry/pry/blob/master/LICENSE
30
+ gem "pry", "~> 0.9"
31
+
32
+ # Don't leave home without a debugger!
33
+ # Two Clause BSD License - https://github.com/cldwalker/debugger/blob/master/LICENSE
34
+ gem "debugger", "~> 1.3", :platforms => :mri
35
+ end
36
+
37
+ group :development do
38
+ # A generic file system event handler; spin it up and see the tests fly
39
+ # MIT License - https://github.com/guard/guard/blob/master/LICENSE
40
+ gem "guard", "~> 1.6"
41
+
42
+ # Guard configuration to manage Gemfile updates
43
+ # MIT License - https://github.com/guard/guard-bundler/blob/master/LICENSE
44
+ gem "guard-bundler", "~> 1.0"
45
+
46
+ # Guard configuration to manage our spork drb environments
47
+ # MIT License - https://github.com/guard/guard-spork/blob/master/LICENSE
48
+ gem "guard-spork", "~> 1.5"
49
+
50
+ # Guard configuration & hooks for rspec
51
+ # MIT License - https://github.com/guard/guard-rspec/blob/master/LICENSE
52
+ gem "guard-rspec", "~> 2.4"
53
+
54
+ # Growl notification protocol gem - give us fancy warnings when things go awry
55
+ # MIT License - https://github.com/snaka/ruby_gntp/blob/master/lib/ruby_gntp.rb
56
+ gem "ruby_gntp", "~> 0.3"
57
+
58
+ # FS event hooks for OS X
59
+ # MIT License - https://github.com/thibaudgg/rb-fsevent/blob/master/LICENSE
60
+ gem "rb-fsevent", "~> 0.9", :require => RUBY_PLATFORM.include?("darwin") && "rb-fsevent"
61
+ end
@@ -0,0 +1,35 @@
1
+ # Touching any of these files should cause the entire test suite to reload.
2
+ GLOBAL_SPEC_FILES = [
3
+ ".rspec",
4
+ %r{^spec/.*_helper\.rb$},
5
+ %r{^spec/common/.*\.rb$},
6
+ "lib/cli_forge.rb",
7
+ "lib/cli_forge/autoload_convention.rb",
8
+ ]
9
+
10
+ def specs_for_path(path)
11
+ ["spec/unit/#{path}_spec.rb", Dir["spec/unit/#{path}/**/*_spec.rb"]].flatten
12
+ end
13
+
14
+ guard "bundler" do
15
+ watch("Gemfile")
16
+ watch(/^.+\.gemspec/)
17
+ end
18
+
19
+ guard "spork", rspec_port: 2733 do
20
+ watch("Gemfile")
21
+ watch("Gemfile.lock")
22
+
23
+ GLOBAL_SPEC_FILES.each do |pattern|
24
+ watch(pattern) { :rspec }
25
+ end
26
+ end
27
+
28
+ guard "rspec", cli: "--drb --drb-port 2733" do
29
+ GLOBAL_SPEC_FILES.each do |pattern|
30
+ watch(pattern) { "spec" }
31
+ end
32
+
33
+ watch(%r{^spec/.+_spec\.rb$})
34
+ watch(%r{^lib/(.+)\.rb$}) { |m| specs_for_path(m[1]) }
35
+ end
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2013 Ian MacLeod <ian@nevir.net>
2
+ ==============================================
3
+
4
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
5
+ this software and associated documentation files (the "Software"), to deal in
6
+ the Software without restriction, including without limitation the rights to
7
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
8
+ the Software, and to permit persons to whom the Software is furnished to do so,
9
+ subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all
12
+ copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
16
+ FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
17
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
18
+ IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19
+ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,30 @@
1
+ CLI Forge [![Gem Version](https://badge.fury.io/rb/cli-forge.png)](https://rubygems.org/gems/cli-forge) [![Build Status](https://secure.travis-ci.org/nevir/cli-forge.png?branch=master)](http://travis-ci.org/nevir/cli-forge) [![Coverage Status](https://coveralls.io/repos/nevir/cli-forge/badge.png?branch=master)](https://coveralls.io/r/nevir/cli-forge) [![Code Climate](https://codeclimate.com/github/nevir/cli-forge.png)](https://codeclimate.com/github/nevir/cli-forge) [![Dependency Status](https://gemnasium.com/nevir/cli-forge.png)](https://gemnasium.com/nevir/cli-forge)
2
+ =========
3
+
4
+ Beat your CLI tool suites into submission!
5
+
6
+ * Create CLI tools that are easily extended (`git style args` -> `git-style args`)
7
+
8
+ * A help system that is friendly to you _and_ your users.
9
+
10
+ * That warm fuzzy feeling of being able to support plugin commands written in
11
+ any language.
12
+
13
+
14
+ Ok... How Do I?
15
+ ===============
16
+
17
+ Let's start with the most basic example:
18
+
19
+ ```ruby
20
+ #!/usr/bin/env ruby
21
+ require "cli-forge"
22
+
23
+ CLIForge.start
24
+ ```
25
+
26
+
27
+ License
28
+ =======
29
+
30
+ [CLI Forge is MIT Licensed](MIT-LICENSE.md).
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ PROJECT_PATH = File.expand_path("..", __FILE__)
5
+ Dir["#{PROJECT_PATH}/tasks/**/*.rake"].each do |path|
6
+ load path
7
+ end
8
+
9
+ $LOAD_PATH.unshift File.join(PROJECT_PATH, "lib")
10
+
11
+
12
+ desc "Run the full test suite"
13
+ task :default => [:spec, :"spec:mutate"]
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ require File.expand_path("../lib/cli_forge/version", __FILE__)
4
+
5
+ Gem::Specification.new do |gem|
6
+ gem.name = "cli-forge"
7
+ gem.version = CLIForge::VERSION
8
+ gem.homepage = "http://github.com/nevir/cli-forge"
9
+ gem.summary = "Beat your CLI tool suites into submission!"
10
+ gem.description = "A library for building CLI tools that are intended to be easily extensible (git style)"
11
+ gem.author = "Ian MacLeod"
12
+ gem.email = "ian@nevir.net"
13
+
14
+ gem.platform = Gem::Platform::RUBY
15
+
16
+ gem.files = `git ls-files`.split($/)
17
+ gem.require_paths = ["lib"]
18
+ end
@@ -0,0 +1 @@
1
+ require "cli_forge"
@@ -0,0 +1,5 @@
1
+ require "cli_forge/autoload_convention"
2
+
3
+ module CLIForge
4
+ extend CLIForge::AutoloadConvention
5
+ end
@@ -0,0 +1,29 @@
1
+ # Autoload Convention
2
+ # ===================
3
+ # We adhere to a strict convention for the constants in this library:
4
+ #
5
+ # `Camel::Caps::BasedConstants` map to their underscore variants of
6
+ # `camel/caps/based_constants`.
7
+ #
8
+ # Each autoloadable parent module/class only needs to to `extend` the
9
+ # `AutoloadConvention` to bootstrap this behavior.
10
+ module CLIForge
11
+ module AutoloadConvention
12
+
13
+ # `autoload` is dead, and we don't want to deal with its removal in 2.0,
14
+ # so here's a thread-unsafe poor man's solution.
15
+ def const_missing(sym)
16
+ full_sym = "#{self.name}::#{sym}"
17
+ path_parts = full_sym.split("::").map { |part|
18
+ part.gsub(/([^A-Z])([A-Z]+)/, "\\1_\\2").downcase
19
+ }
20
+
21
+ require File.join(*path_parts)
22
+
23
+ # Make sure that we don't get stuck in an endless loop. `const_get` calls
24
+ # into `const_missing`, so we can't use that.
25
+ eval "defined?(#{full_sym}) ? #{full_sym} : super"
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ module CLIForge
2
+ VERSION = "0.0.0"
3
+ end
@@ -0,0 +1,5 @@
1
+ module Fixtures; end
2
+
3
+ module Fixtures::AutoloadConvention
4
+ ALLCAPS = :yelling
5
+ end
@@ -0,0 +1 @@
1
+ module WrongConstant; end
@@ -0,0 +1,5 @@
1
+ module Fixtures; end
2
+
3
+ module Fixtures::AutoloadConvention
4
+ MultiToken = :multi
5
+ end
@@ -0,0 +1,5 @@
1
+ module Fixtures; end
2
+
3
+ module Fixtures::AutoloadConvention
4
+ Single = :single_and_stuff
5
+ end
@@ -0,0 +1,5 @@
1
+ module Fixtures; end
2
+
3
+ module Fixtures::AutoloadConvention
4
+ String = "I am a string!"
5
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "spork"
3
+ require "spork/ext/ruby-debug"
4
+ rescue LoadError
5
+ # No spork? No problem!
6
+ module Spork
7
+ def self.prefork
8
+ yield
9
+ end
10
+
11
+ def self.each_run
12
+ yield
13
+ end
14
+ end
15
+ end
16
+
17
+ Spork.prefork do
18
+ # Allow requires relative to the spec dir
19
+ SPEC_ROOT = File.expand_path("..", __FILE__)
20
+ $LOAD_PATH << SPEC_ROOT
21
+
22
+ require "rspec"
23
+ require "timeout"
24
+
25
+ # Load our spec environment (random to avoid dependency ordering)
26
+ Dir[File.join(SPEC_ROOT, "common", "*.rb")].shuffle.each do |helper|
27
+ require "common/#{File.basename(helper, ".rb")}"
28
+ end
29
+
30
+ RSpec.configure do |config|
31
+ config.treat_symbols_as_metadata_keys_with_true_values = true
32
+
33
+ # We enforce expect(...) style syntax to avoid mucking around in Core
34
+ config.expect_with :rspec do |c|
35
+ c.syntax = :expect
36
+ end
37
+
38
+ # Time out specs (particularly useful for mutant)
39
+ config.around(:each) do |spec|
40
+ timeout(0.5) { spec.run }
41
+ end
42
+
43
+ # Be verbose about warnings
44
+ config.around(:each) do |spec|
45
+ old_verbose = $VERBOSE
46
+ # Or not at all if we are in mutation testing
47
+ $VERBOSE = ENV["MUTATION"] ? nil : 2
48
+
49
+ spec.run
50
+
51
+ $VERBOSE = old_verbose
52
+ end
53
+ end
54
+ end
55
+
56
+ Spork.each_run do
57
+ # The rspec test runner executes the specs in a separate process; plus it's nice to have this
58
+ # generic flag for cases where you want coverage running with guard.
59
+ if ENV["COVERAGE"]
60
+ require "simplecov"
61
+
62
+ if ENV["CONTINUOUS_INTEGRATION"]
63
+ require "coveralls"
64
+ Coveralls.wear!
65
+ end
66
+ end
67
+
68
+ # Because we're an autoloading lib, just require the root up front.
69
+ #
70
+ # Must be loaded _after_ `simplecov`, otherwise it won't pick up on requires.
71
+ require "cli_forge"
72
+ end
73
+
@@ -0,0 +1,49 @@
1
+ describe CLIForge::AutoloadConvention, "#const_missing" do
2
+
3
+ let(:namespace) {
4
+ mod = Module.new do
5
+ class << self
6
+ def name
7
+ "Fixtures::AutoloadConvention"
8
+ end
9
+ alias_method :inspect, :name
10
+ end
11
+ end
12
+ mod.extend subject
13
+
14
+ mod
15
+ }
16
+
17
+ it "should raise a LoadError when referencing an unknown constant" do
18
+ expect { namespace::Foo }.to raise_error(LoadError)
19
+ end
20
+
21
+ it "should raise a NameError when the file exists, but the wrong constant is defined" do
22
+ expect { namespace::Mismatched }.to raise_error(NameError)
23
+ end
24
+
25
+ it "should load single-token files" do
26
+ namespace.should_receive(:require).with("fixtures/autoload_convention/single").and_call_original
27
+
28
+ expect(namespace::Single).to eq(:single_and_stuff)
29
+ end
30
+
31
+ it "should load multi-token files" do
32
+ namespace.should_receive(:require).with("fixtures/autoload_convention/multi_token").and_call_original
33
+
34
+ expect(namespace::MultiToken).to eq(:multi)
35
+ end
36
+
37
+ it "shouldn't split ACRONYMS" do
38
+ namespace.should_receive(:require).with("fixtures/autoload_convention/allcaps").and_call_original
39
+
40
+ expect(namespace::ALLCAPS).to eq(:yelling)
41
+ end
42
+
43
+ it "shouldn't pick up constants in parent namespaces" do
44
+ namespace.should_receive(:require).with("fixtures/autoload_convention/string").and_call_original
45
+
46
+ expect(namespace::String).to eq("I am a string!")
47
+ end
48
+
49
+ end
@@ -0,0 +1,7 @@
1
+ desc "Boot up a console w/ cli-forge preloaded"
2
+ task :console do
3
+ require "cli-forge"
4
+ require "pry"
5
+
6
+ Pry.start
7
+ end
@@ -0,0 +1,5 @@
1
+ require "rspec/core/rake_task"
2
+
3
+ RSpec::Core::RakeTask.new(:spec) do |task|
4
+ # No special configuration yet.
5
+ end
@@ -0,0 +1,20 @@
1
+ namespace :spec do
2
+
3
+ desc "Run the tests in CI mode"
4
+ task :ci do
5
+ prev = ENV["CONTINUOUS_INTEGRATION"]
6
+ ENV["CONTINUOUS_INTEGRATION"] = "yes"
7
+
8
+ # Simplecov doesn't support 1.8
9
+ unless RUBY_VERSION.start_with? "1.8"
10
+ Rake::Task["spec:coverage"].execute
11
+ else
12
+ Rake::Task["spec"].execute
13
+ end
14
+
15
+ Rake::Task["spec:mutate"].execute
16
+
17
+ ENV["CONTINUOUS_INTEGRATION"] = prev
18
+ end
19
+
20
+ end
@@ -0,0 +1,17 @@
1
+ namespace :spec do
2
+
3
+ desc "Run tests with code coverage"
4
+ task :coverage do
5
+ prev = ENV["COVERAGE"]
6
+ ENV["COVERAGE"] = "yes"
7
+
8
+ Rake::Task["spec"].execute
9
+
10
+ if RUBY_PLATFORM.include? "darwin"
11
+ `open #{File.join(PROJECT_PATH, "coverage", "index.html")}`
12
+ end
13
+
14
+ ENV["COVERAGE"] = prev
15
+ end
16
+
17
+ end
@@ -0,0 +1,50 @@
1
+ namespace :spec do
2
+
3
+ def mutant_supported?
4
+ return false unless RUBY_VERSION.start_with?("1.9")
5
+
6
+ begin
7
+ return false unless RUBY_ENGINE == "ruby" || RUBY_ENGINE == "rbx"
8
+ rescue NameError
9
+ return false
10
+ end
11
+
12
+ true
13
+ end
14
+
15
+ desc "Runs tests with code mutation"
16
+ task :mutate, [:focus_on] do |t, args|
17
+ next unless mutant_supported?
18
+
19
+ require "cli_forge"
20
+ require "mutant"
21
+
22
+ # You can focus on a particular symbol/method by passing it to the task:
23
+ # rake spec:mutate[AutoloadConvention#const_missing], for example.
24
+ if args.focus_on
25
+ matcher = Mutant::Matcher.from_string("::CLIForge::#{args.focus_on}")
26
+ else
27
+ matcher = Mutant::Matcher::ObjectSpace.new(/\ACLIForge(::|#|\.).+\Z/)
28
+ end
29
+
30
+ # Mutant doesn't have a public scripting API yet; so we're cheating.
31
+ config = {}
32
+ def config.method_missing(sym)
33
+ self[sym]
34
+ end
35
+
36
+ config.merge!(
37
+ :strategy => Mutant::Strategy::Rspec::DM2.new(config),
38
+ :killer => Mutant::Killer::Rspec,
39
+ :matcher => matcher,
40
+ :filter => Mutant::Mutation::Filter::ALL,
41
+ :reporter => Mutant::Reporter::CLI.new(config)
42
+ )
43
+
44
+ ENV["MUTATION"] = "yes"
45
+ if Mutant::Runner.run(config).fail?
46
+ exit 1
47
+ end
48
+ end
49
+
50
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cli-forge
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Ian MacLeod
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-02 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A library for building CLI tools that are intended to be easily extensible
15
+ (git style)
16
+ email: ian@nevir.net
17
+ executables: []
18
+ extensions: []
19
+ extra_rdoc_files: []
20
+ files:
21
+ - .gitignore
22
+ - .rspec
23
+ - .simplecov
24
+ - .travis.yml
25
+ - Gemfile
26
+ - Guardfile
27
+ - MIT-LICENSE.md
28
+ - README.md
29
+ - Rakefile
30
+ - cli-forge.gemspec
31
+ - lib/cli-forge.rb
32
+ - lib/cli_forge.rb
33
+ - lib/cli_forge/autoload_convention.rb
34
+ - lib/cli_forge/version.rb
35
+ - spec/fixtures/autoload_convention/allcaps.rb
36
+ - spec/fixtures/autoload_convention/mismatched.rb
37
+ - spec/fixtures/autoload_convention/multi_token.rb
38
+ - spec/fixtures/autoload_convention/single.rb
39
+ - spec/fixtures/autoload_convention/string.rb
40
+ - spec/spec_helper.rb
41
+ - spec/unit/cli_forge/autoload_convention/const_missing_spec.rb
42
+ - tasks/console.rake
43
+ - tasks/spec.rake
44
+ - tasks/spec/ci.rake
45
+ - tasks/spec/coverage.rake
46
+ - tasks/spec/mutate.rake
47
+ homepage: http://github.com/nevir/cli-forge
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.23
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Beat your CLI tool suites into submission!
71
+ test_files: []