quickl 0.1.1

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