quickl 0.1.1

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.
Files changed (46) hide show
  1. data/CHANGELOG.md +9 -0
  2. data/README.md +118 -0
  3. data/Rakefile +64 -0
  4. data/bin/quickl +116 -0
  5. data/examples/delegate/README.md +86 -0
  6. data/examples/delegate/bin/delegate +9 -0
  7. data/examples/delegate/lib/delegate.rb +41 -0
  8. data/examples/delegate/lib/hello_world.rb +39 -0
  9. data/examples/delegate/lib/help.rb +24 -0
  10. data/examples/delegate/test/delegate_test.rb +68 -0
  11. data/examples/hello/README.md +74 -0
  12. data/examples/hello/hello +57 -0
  13. data/examples/hello/hello_test.rb +65 -0
  14. data/examples/helper.rb +6 -0
  15. data/lib/quickl.rb +47 -0
  16. data/lib/quickl/command.rb +154 -0
  17. data/lib/quickl/command/builder.rb +58 -0
  18. data/lib/quickl/command/delegate.rb +53 -0
  19. data/lib/quickl/command/options.rb +55 -0
  20. data/lib/quickl/command/robustness.rb +18 -0
  21. data/lib/quickl/command/single.rb +27 -0
  22. data/lib/quickl/errors.rb +196 -0
  23. data/lib/quickl/ext/object.rb +29 -0
  24. data/lib/quickl/naming.rb +53 -0
  25. data/lib/quickl/ruby_tools.rb +60 -0
  26. data/quickl.gemspec +38 -0
  27. data/templates/single.erb +40 -0
  28. data/test/command/command_name.spec +16 -0
  29. data/test/command/documentation.spec +23 -0
  30. data/test/command/overview.spec +14 -0
  31. data/test/command/run.spec +22 -0
  32. data/test/command/subcommands.spec +20 -0
  33. data/test/command/usage.spec +16 -0
  34. data/test/mini_client.rb +59 -0
  35. data/test/naming/command2module.spec +17 -0
  36. data/test/naming/module2command.spec +21 -0
  37. data/test/ruby_tools/class_unqualified_name.spec +28 -0
  38. data/test/ruby_tools/extract_file_rdoc.spec +28 -0
  39. data/test/ruby_tools/fixtures.rb +27 -0
  40. data/test/ruby_tools/fixtures/RubyTools.rdoc +12 -0
  41. data/test/ruby_tools/fixtures/Utils.rdoc +3 -0
  42. data/test/ruby_tools/optional_args_block_call.spec +37 -0
  43. data/test/ruby_tools/parent_module.spec +23 -0
  44. data/test/spec_helper.rb +13 -0
  45. data/test/wrapping.rb +39 -0
  46. metadata +129 -0
@@ -0,0 +1,60 @@
1
+ module Quickl
2
+ module RubyTools
3
+
4
+ # Returns the parent module of a class
5
+ def parent_module(clazz)
6
+ name = clazz.name
7
+ (name =~ /^(.*?)::([^:]+)$/) ? Kernel.eval($1) : nil
8
+ end
9
+ module_function :parent_module
10
+
11
+ # Returns the unqualified name of a class
12
+ def class_unqualified_name(clazz)
13
+ name = clazz.name
14
+ (name =~ /::([^:]+)$/) ? $1 : name
15
+ end
16
+ module_function :class_unqualified_name
17
+
18
+ # Makes a call to a block that accepts optional arguments
19
+ def optional_args_block_call(block, args)
20
+ if RUBY_VERSION >= "1.9.0"
21
+ if block.arity == 0
22
+ block.call
23
+ else
24
+ block.call(*args)
25
+ end
26
+ else
27
+ block.call(*args)
28
+ end
29
+ end
30
+ module_function :optional_args_block_call
31
+
32
+ # Extracts the rdoc of a given ruby file source.
33
+ def extract_file_rdoc(file, from = nil, reverse = false)
34
+ lines = File.readlines(file)
35
+ if from.nil? and reverse
36
+ lines = lines.reverse
37
+ elsif !reverse
38
+ lines = lines[(from || 0)..-1]
39
+ else
40
+ lines = lines[0...(from || -1)].reverse
41
+ end
42
+
43
+ doc, started = [], false
44
+ lines.each{|line|
45
+ if /^\s*[#]/ =~ line
46
+ doc << line
47
+ started = true
48
+ elsif started
49
+ break
50
+ end
51
+ }
52
+
53
+ doc = reverse ? doc.reverse[0..-1] : doc[0..-1]
54
+ doc = doc.join("\n")
55
+ doc.gsub(/^\s*[#] ?/, "")
56
+ end
57
+ module_function :extract_file_rdoc
58
+
59
+ end # module RubyTools
60
+ end # module Quickl
@@ -0,0 +1,38 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+ require 'rubygems'
3
+ require 'quickl'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'quickl'
7
+ s.version = Quickl::VERSION.dup
8
+ s.date = Time.now.strftime('%Y-%m-%d')
9
+
10
+ s.summary = 'Generate Ruby command line apps quickly'
11
+ s.description = 'Generate Ruby command line apps quickly'
12
+
13
+ s.author = 'Bernard Lambeau'
14
+ s.email = 'blambeau@gmail.com'
15
+
16
+ s.require_paths = %w{ lib }
17
+
18
+ s.files =
19
+ Dir['lib/**/*'] +
20
+ Dir['examples/**/*'] +
21
+ Dir['templates/**/*'] +
22
+ Dir['bin/**/*'] +
23
+ Dir['test/**/*'] +
24
+ %w{ quickl.gemspec Rakefile README.md CHANGELOG.md }
25
+
26
+ s.test_files = s.files.select {|path| path =~ /^test\/.*_test.rb/ }
27
+
28
+ s.bindir = "bin"
29
+ s.executables = ["quickl"]
30
+
31
+ s.add_development_dependency('rake')
32
+
33
+ s.has_rdoc = true
34
+ s.rdoc_options = %w< --line-numbers --inline-source --title Quickl --main Quickl >
35
+ s.extra_rdoc_files = %w< README.md >
36
+
37
+ s.homepage = 'http://github.com/blambeau/quickl'
38
+ end
@@ -0,0 +1,40 @@
1
+ begin
2
+ require 'quickl'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ gem 'quickl'
6
+ retry
7
+ end
8
+
9
+ #
10
+ # FIX: overview
11
+ #
12
+ # SYNOPSIS
13
+ # #{command_name} [options] ARGS...
14
+ #
15
+ # OPTIONS
16
+ # #{summarized_options}
17
+ #
18
+ # DESCRIPTION
19
+ # FIX: description
20
+ #
21
+ class <%= cmd_class_name %> < Quickl::Command(__FILE__, __LINE__)
22
+
23
+ VERSION = "0.1.0"
24
+
25
+ # Install options
26
+ options do |opt|
27
+ <%= option_helpers.collect{|s| tabto(s,4)}.join("\n") %>
28
+ end
29
+
30
+ # Run the command
31
+ def execute(args)
32
+ # FIX: do something here
33
+ puts "Hello #{args.join(' and ')} from #{program_name}"
34
+ end
35
+
36
+ end # class <%= cmd_class_name %>
37
+
38
+ if __FILE__ == $0
39
+ <%= cmd_class_name %>.run(ARGV)
40
+ end
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Command::command_name /" do
4
+
5
+ it "should be installed from inline rdoc" do
6
+ MiniClient::Say::Hello.command_name.should == "hello"
7
+ MiniClient::Say::Goodbye.command_name.should == "goodbye"
8
+ end
9
+
10
+ it "should be accessible on instance" do
11
+ MiniClient::Say::Hello.new.command_name.should == "hello"
12
+ MiniClient::Say::Goodbye.new.command_name.should == "goodbye"
13
+ end
14
+
15
+ end # Command::command_name
16
+ end # module Quickl
@@ -0,0 +1,23 @@
1
+ $hello_doc = <<EOF
2
+
3
+ Say hello to the user whose name is requested on the standard input
4
+
5
+ SYNOPSIS
6
+ mini-client say:hello
7
+
8
+ DESCRIPTION
9
+ And an explanation here
10
+ on multiple lines with replacement: hello
11
+
12
+ EOF
13
+
14
+ require File.expand_path('../../spec_helper', __FILE__)
15
+ module Quickl
16
+ describe "Command::documentation /" do
17
+
18
+ it "should be correctly installed" do
19
+ MiniClient::Say::Hello.documentation.should == $hello_doc[0..-1]
20
+ end
21
+
22
+ end # Command::command
23
+ end # module Quickl
@@ -0,0 +1,14 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Command::overview /" do
4
+
5
+ it "should be installed from inline rdoc" do
6
+ MiniClient::Help.overview.should == "Print help"
7
+ end
8
+
9
+ it "should be installed accessible on instance" do
10
+ MiniClient::Help.new.overview.should == "Print help"
11
+ end
12
+
13
+ end # Command::overview
14
+ end # module Quickl
@@ -0,0 +1,22 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Command::run /" do
4
+
5
+ it "when invoked on a terminal command" do
6
+ MiniClient::Say::Hello.run.should == :hello
7
+ MiniClient::Say::Goodbye.run.should == :goodbye
8
+ end
9
+
10
+ it "when invoked on a delegate command" do
11
+ MiniClient.run(["help"]).should == :help
12
+ MiniClient::Say.run(["hello"]).should == :hello
13
+ MiniClient::Say.run(["goodbye"]).should == :goodbye
14
+ end
15
+
16
+ it "when invoked on qualified command names" do
17
+ MiniClient.run(["say:hello"]).should == :hello
18
+ MiniClient.run(["say:goodbye"]).should == :goodbye
19
+ end
20
+
21
+ end # Command::command
22
+ end # module Quickl
@@ -0,0 +1,20 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Command::subcommands /" do
4
+
5
+ it "should return installed commands in an array" do
6
+ MiniClient.subcommands.should == [
7
+ MiniClient::Help,
8
+ MiniClient::Say
9
+ ]
10
+ end
11
+
12
+ it "should return installed commands in an array" do
13
+ MiniClient::Say.subcommands.should == [
14
+ MiniClient::Say::Hello,
15
+ MiniClient::Say::Goodbye
16
+ ]
17
+ end
18
+
19
+ end # Command::subcommand
20
+ end # module Quickl
@@ -0,0 +1,16 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Command::usage /" do
4
+
5
+ it "should be installed from inline rdoc" do
6
+ MiniClient::Say::Hello.usage.should == "mini-client say:hello"
7
+ MiniClient::Say::Goodbye.usage.should == "mini-client say:goodbye"
8
+ end
9
+
10
+ it "should be accessible on instance" do
11
+ MiniClient::Say::Hello.new.usage.should == "mini-client say:hello"
12
+ MiniClient::Say::Goodbye.new.usage.should == "mini-client say:goodbye"
13
+ end
14
+
15
+ end # Command::usage
16
+ end # module Quickl
@@ -0,0 +1,59 @@
1
+ #
2
+ # MiniClient main command
3
+ #
4
+ class MiniClient < Quickl::Delegate(__FILE__, __LINE__)
5
+
6
+ #
7
+ # Print help
8
+ #
9
+ # SYNOPSIS
10
+ # #{MiniClient.command_name} help
11
+ #
12
+ # DESCRIPTION
13
+ # #{command_name} prints help
14
+ #
15
+ class Help < Quickl::Command(__FILE__, __LINE__)
16
+
17
+ def run(*args)
18
+ :help
19
+ end
20
+
21
+ end # class Help
22
+
23
+ class Say < Quickl::Delegate(__FILE__, __LINE__)
24
+
25
+ #
26
+ # Say hello to the user whose name is requested on the standard input
27
+ #
28
+ # SYNOPSIS
29
+ # #{MiniClient.command_name} say:hello
30
+ #
31
+ # DESCRIPTION
32
+ # And an explanation here
33
+ # on multiple lines with replacement: #{command_name}
34
+ #
35
+ class Hello < Quickl::Command(__FILE__, __LINE__)
36
+
37
+ def run(*args)
38
+ :hello
39
+ end
40
+
41
+ end # class Hello
42
+
43
+ #
44
+ # Say goodbye to the currently connected user
45
+ #
46
+ # SYNOPSIS
47
+ # #{MiniClient.command_name} say:goodbye
48
+ #
49
+ class Goodbye < Quickl::Command(__FILE__, __LINE__)
50
+
51
+ def run(*args)
52
+ :goodbye
53
+ end
54
+
55
+ end # class Goodbye
56
+
57
+ end # class Say
58
+
59
+ end # module MiniClient
@@ -0,0 +1,17 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Naming::command2module /" do
4
+ include Naming
5
+
6
+ it "should capitalize first char" do
7
+ command2module("say").should == "Say"
8
+ command2module(:say).should == :Say
9
+ end
10
+
11
+ it "should capitalize support dashes" do
12
+ command2module("say-hello").should == "SayHello"
13
+ command2module(:"say-hello").should == :SayHello
14
+ end
15
+
16
+ end # module Quickl
17
+ end # module Quickl
@@ -0,0 +1,21 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ describe "Naming::module2command /" do
4
+ include Naming
5
+
6
+ it "should uncapitalize first char" do
7
+ module2command("Say").should == "say"
8
+ module2command(:Say).should == :say
9
+ end
10
+
11
+ it "should uncapitalize and introduce dashes" do
12
+ module2command("SayHello").should == "say-hello"
13
+ module2command(:"SayHello").should == :"say-hello"
14
+ end
15
+
16
+ it "should support taking modules as argument" do
17
+ module2command(Quickl::Command).should == "command"
18
+ end
19
+
20
+ end # module Quickl
21
+ end # module Quickl
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../fixtures', __FILE__)
2
+ module Quickl
3
+ describe "RubyTools#class_unqualified_name /" do
4
+
5
+ subject{ RubyTools::class_unqualified_name(clazz) }
6
+
7
+ describe "when called on unqualified class" do
8
+ let(:clazz){ ::String }
9
+ it{ should == "String" }
10
+ end
11
+
12
+ describe "when called on qualified class" do
13
+ let(:clazz){ RubyTools }
14
+ it{ should == "RubyTools" }
15
+ end
16
+
17
+ describe "when called on long qualified class" do
18
+ let(:clazz){ Quickl::Fixtures::Utils }
19
+ it{ should == "Utils" }
20
+ end
21
+
22
+ describe "when piped with parent_module" do
23
+ let(:clazz){ RubyTools::parent_module(Quickl::Fixtures::Utils) }
24
+ it{ should == "Fixtures" }
25
+ end
26
+
27
+ end
28
+ end
@@ -0,0 +1,28 @@
1
+ require File.expand_path('../fixtures', __FILE__)
2
+ module Quickl
3
+ describe "RubyTools#extract_file_rdoc /" do
4
+
5
+ let(:file){ File.expand_path('../fixtures.rb', __FILE__) }
6
+
7
+ describe "when used without line and reverse options" do
8
+
9
+ subject{ RubyTools::extract_file_rdoc(file) }
10
+
11
+ it "should be as expected" do
12
+ subject.should == File.read(File.expand_path('../fixtures/RubyTools.rdoc', __FILE__))
13
+ end
14
+
15
+ end
16
+
17
+ describe "when used with line and reverse options" do
18
+
19
+ subject{ RubyTools::extract_file_rdoc(file, 23, true) }
20
+
21
+ it "should be as expected" do
22
+ subject.should == File.read(File.expand_path('../fixtures/Utils.rdoc', __FILE__))
23
+ end
24
+
25
+ end
26
+
27
+ end # RubyTools#extract_file_rdoc
28
+ end # module Quickl
@@ -0,0 +1,27 @@
1
+ require File.expand_path('../../spec_helper', __FILE__)
2
+ module Quickl
3
+ module Fixtures
4
+
5
+ #
6
+ # This is a fixtures helper that matches documentation conventions.
7
+ #
8
+ # This is a second paragraph
9
+ # That append on two lines
10
+ #
11
+ #
12
+ # WARNING:
13
+ # This kind of indentation should not be interpreted as code
14
+ #
15
+ # But this one yes
16
+ #
17
+ module RubyTools
18
+ end # module RubyTools
19
+
20
+ #
21
+ # This is the documentation of the Utils module
22
+ #
23
+ module Utils
24
+ end # module Utils
25
+
26
+ end # module Fixtures
27
+ end # module Quickl