quickl 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +9 -0
- data/README.md +118 -0
- data/Rakefile +64 -0
- data/bin/quickl +116 -0
- data/examples/delegate/README.md +86 -0
- data/examples/delegate/bin/delegate +9 -0
- data/examples/delegate/lib/delegate.rb +41 -0
- data/examples/delegate/lib/hello_world.rb +39 -0
- data/examples/delegate/lib/help.rb +24 -0
- data/examples/delegate/test/delegate_test.rb +68 -0
- data/examples/hello/README.md +74 -0
- data/examples/hello/hello +57 -0
- data/examples/hello/hello_test.rb +65 -0
- data/examples/helper.rb +6 -0
- data/lib/quickl.rb +47 -0
- data/lib/quickl/command.rb +154 -0
- data/lib/quickl/command/builder.rb +58 -0
- data/lib/quickl/command/delegate.rb +53 -0
- data/lib/quickl/command/options.rb +55 -0
- data/lib/quickl/command/robustness.rb +18 -0
- data/lib/quickl/command/single.rb +27 -0
- data/lib/quickl/errors.rb +196 -0
- data/lib/quickl/ext/object.rb +29 -0
- data/lib/quickl/naming.rb +53 -0
- data/lib/quickl/ruby_tools.rb +60 -0
- data/quickl.gemspec +38 -0
- data/templates/single.erb +40 -0
- data/test/command/command_name.spec +16 -0
- data/test/command/documentation.spec +23 -0
- data/test/command/overview.spec +14 -0
- data/test/command/run.spec +22 -0
- data/test/command/subcommands.spec +20 -0
- data/test/command/usage.spec +16 -0
- data/test/mini_client.rb +59 -0
- data/test/naming/command2module.spec +17 -0
- data/test/naming/module2command.spec +21 -0
- data/test/ruby_tools/class_unqualified_name.spec +28 -0
- data/test/ruby_tools/extract_file_rdoc.spec +28 -0
- data/test/ruby_tools/fixtures.rb +27 -0
- data/test/ruby_tools/fixtures/RubyTools.rdoc +12 -0
- data/test/ruby_tools/fixtures/Utils.rdoc +3 -0
- data/test/ruby_tools/optional_args_block_call.spec +37 -0
- data/test/ruby_tools/parent_module.spec +23 -0
- data/test/spec_helper.rb +13 -0
- data/test/wrapping.rb +39 -0
- 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
|
data/quickl.gemspec
ADDED
@@ -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
|
data/test/mini_client.rb
ADDED
@@ -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
|