cli-forge 0.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []