gestopft 0.0.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.
- data/.autotest +8 -0
- data/.rspec +4 -0
- data/README.rdoc +38 -0
- data/lib/gestopft.rb +16 -0
- data/lib/gestopft/app.rb +101 -0
- data/lib/gestopft/core_ext.rb +10 -0
- data/lib/gestopft/core_ext/array.rb +10 -0
- data/lib/gestopft/core_ext/string.rb +14 -0
- data/lib/gestopft/core_ext/symbol.rb +10 -0
- data/lib/gestopft/option.rb +25 -0
- data/spec/gestopft/option_spec.rb +63 -0
- data/spec/gestopft_spec.rb +83 -0
- metadata +67 -0
data/.autotest
ADDED
data/.rspec
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
= gestopft
|
2
|
+
|
3
|
+
== Description
|
4
|
+
|
5
|
+
Framework for CLI Application (like {App::CLI}[http://search.cpan.org/dist/App-CLI/])
|
6
|
+
|
7
|
+
|
8
|
+
== Installation
|
9
|
+
|
10
|
+
=== Archive
|
11
|
+
|
12
|
+
rake install
|
13
|
+
|
14
|
+
=== Gem
|
15
|
+
|
16
|
+
gem install gestopft
|
17
|
+
|
18
|
+
|
19
|
+
== Synopsis
|
20
|
+
|
21
|
+
require "gestopft"
|
22
|
+
|
23
|
+
class Echo < Gestopft::App
|
24
|
+
option :verbose, "print debug messages."
|
25
|
+
|
26
|
+
def echo(message)
|
27
|
+
puts "Echo#echo is invoked." if @options[:verbose]
|
28
|
+
puts message
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
== Copyright
|
34
|
+
|
35
|
+
Copyright:: Copyright (c) 2011 AOKI,Hanae
|
36
|
+
Author:: AOKI,Hanae (aereal, trasty.loose@gmail.com)
|
37
|
+
License:: Ruby's
|
38
|
+
|
data/lib/gestopft.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
require "gestopft/core_ext"
|
4
|
+
|
5
|
+
module Gestopft
|
6
|
+
VERSION = '0.0.1'
|
7
|
+
|
8
|
+
module Constants
|
9
|
+
class Error < ::StandardError; end
|
10
|
+
class NotSatisfiedRequirements < Error; end
|
11
|
+
end
|
12
|
+
|
13
|
+
autoload :App, 'gestopft/app'
|
14
|
+
autoload :Option, 'gestopft/option'
|
15
|
+
end
|
16
|
+
|
data/lib/gestopft/app.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# -*- encoding: utf-8
|
2
|
+
|
3
|
+
class Gestopft::App
|
4
|
+
include Gestopft::Constants
|
5
|
+
|
6
|
+
def self.expectation
|
7
|
+
@expectation ||= []
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.option(name, *args)
|
11
|
+
desc = args.find {|arg| arg.is_a? String }
|
12
|
+
params = args.find {|arg| arg.is_a? Array }
|
13
|
+
expectation << Gestopft::Option.new(name, {
|
14
|
+
:desc => desc,
|
15
|
+
:params => params
|
16
|
+
})
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.run(argv)
|
20
|
+
new(argv).parse_arg.dispatch
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.commands
|
24
|
+
public_instance_methods - Gestopft::App.public_instance_methods
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :options
|
28
|
+
|
29
|
+
def initialize(argv)
|
30
|
+
@argv = argv.option_args
|
31
|
+
@expectation = self.class.expectation
|
32
|
+
@options = {}
|
33
|
+
@commands = self.class.commands.map {|cmd| method(cmd) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def parse_arg
|
37
|
+
@expectation.each do |opt|
|
38
|
+
if opt.require_args?
|
39
|
+
if (
|
40
|
+
pos = @argv.find_index(opt.option_name) and
|
41
|
+
params = @argv[pos + 1, opt.arity] and
|
42
|
+
params.none? {|param| param.option? } and
|
43
|
+
params.size == opt.arity
|
44
|
+
)
|
45
|
+
@options[opt.name] = params
|
46
|
+
else
|
47
|
+
raise NotSatisfiedRequirements
|
48
|
+
end
|
49
|
+
else
|
50
|
+
@options[opt.name] = opt.option_name
|
51
|
+
end
|
52
|
+
end
|
53
|
+
self
|
54
|
+
end
|
55
|
+
|
56
|
+
def dispatch
|
57
|
+
argv = @argv.reject {|arg| arg.option? }
|
58
|
+
@commands.each do |cmd|
|
59
|
+
if pos = argv.find_index(cmd.name.to_s)
|
60
|
+
params = argv[pos + 1, cmd.arity.abs]
|
61
|
+
return cmd.call(*params)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
self
|
65
|
+
end
|
66
|
+
|
67
|
+
def help_message
|
68
|
+
msg = []
|
69
|
+
msg << <<-BANNER.strip
|
70
|
+
Usage:
|
71
|
+
$ #{File.basename($0)} [options] #{"command [args, ...]" unless @commands.empty?}
|
72
|
+
BANNER
|
73
|
+
|
74
|
+
unless @expectation.empty?
|
75
|
+
msg << "Options: "
|
76
|
+
@expectation.each do |opt|
|
77
|
+
line = ["\t", opt.option_name]
|
78
|
+
line << opt.params.map {|param|
|
79
|
+
param.to_s.upcase
|
80
|
+
}.join(' ') unless opt.params.empty?
|
81
|
+
line << opt.desc unless opt.desc.empty?
|
82
|
+
msg << line.join(" ")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
unless @commands.empty?
|
87
|
+
msg << <<-COMMANDS.strip
|
88
|
+
Commands:
|
89
|
+
#{@commands.map {|cmd| cmd.name }.join(' ')}
|
90
|
+
COMMANDS
|
91
|
+
end
|
92
|
+
|
93
|
+
msg << ""
|
94
|
+
msg.join("\n\n")
|
95
|
+
end
|
96
|
+
|
97
|
+
def __default__
|
98
|
+
STDIN.puts help_message
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
class Gestopft::Option
|
4
|
+
attr_reader :name, :params, :description
|
5
|
+
alias_method :desc, :description
|
6
|
+
|
7
|
+
def initialize(name, args={})
|
8
|
+
@name = name
|
9
|
+
@params = args[:params] || []
|
10
|
+
@description = args[:desc] || args[:description] || ""
|
11
|
+
end
|
12
|
+
|
13
|
+
def option_name
|
14
|
+
@name.to_option
|
15
|
+
end
|
16
|
+
|
17
|
+
def require_args?
|
18
|
+
!@params.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def arity
|
22
|
+
@params.size
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# vim:set ft=ruby:
|
3
|
+
|
4
|
+
require "gestopft"
|
5
|
+
|
6
|
+
include Gestopft::Constants
|
7
|
+
|
8
|
+
describe Gestopft::Option do
|
9
|
+
subject do
|
10
|
+
Gestopft::Option.new(:my_option, :desc => "my description")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "#option_name is option string." do
|
14
|
+
subject.option_name.should == '--my-option'
|
15
|
+
end
|
16
|
+
|
17
|
+
context "when given a description." do
|
18
|
+
it "#desc[ription] is the description about the option." do
|
19
|
+
subject.desc.should == "my description"
|
20
|
+
subject.description.should == "my description"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when does not given a description." do
|
25
|
+
subject do
|
26
|
+
Gestopft::Option.new(:my_option)
|
27
|
+
end
|
28
|
+
|
29
|
+
it "#desc[ription] is empty." do
|
30
|
+
subject.desc.should be_empty
|
31
|
+
subject.description.should be_empty
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
context "which requires parameters." do
|
36
|
+
subject do
|
37
|
+
Gestopft::Option.new(:delay, :params => %w(minute))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "#require_args? is true" do
|
41
|
+
subject.require_args?.should be_true
|
42
|
+
end
|
43
|
+
|
44
|
+
it "#arity is the arity of option." do
|
45
|
+
subject.arity.should == 1
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context "which requires no parameter." do
|
50
|
+
subject do
|
51
|
+
Gestopft::Option.new(:verbose)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "#require_args? is false" do
|
55
|
+
subject.require_args?.should be_false
|
56
|
+
end
|
57
|
+
|
58
|
+
it "#arity is 0." do
|
59
|
+
subject.arity.should == 0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# vim: set ft=ruby:
|
3
|
+
|
4
|
+
require "gestopft"
|
5
|
+
|
6
|
+
include Gestopft::Constants
|
7
|
+
|
8
|
+
describe Gestopft::App do
|
9
|
+
subject do
|
10
|
+
Class.new(Gestopft::App)
|
11
|
+
end
|
12
|
+
|
13
|
+
context "given a option which requires no arguments." do
|
14
|
+
before :all do
|
15
|
+
subject.module_eval do
|
16
|
+
option :with_no_args
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
it "has a option which given." do
|
21
|
+
subject.run(%w(--with-no-args)).options.
|
22
|
+
should include(:with_no_args)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "does not have a option which does not given." do
|
26
|
+
subject.run(%w(--with-no-args)).options.
|
27
|
+
should_not include(:does_not_given)
|
28
|
+
end
|
29
|
+
|
30
|
+
it "succeeds when given a option which requires no arguments." do
|
31
|
+
expect { subject.run(%w(--with-no-args)) }.
|
32
|
+
should_not raise_error(Error)
|
33
|
+
end
|
34
|
+
|
35
|
+
it "succeeds when not given a option which is required." do
|
36
|
+
expect { subject.run([]) }.
|
37
|
+
should_not raise_error(NotSatisfiedRequirements)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "a option which require a argument." do
|
42
|
+
before :all do
|
43
|
+
subject.module_eval do
|
44
|
+
option :delay, [:minute]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
it "has a option which given with taken parameter." do
|
49
|
+
subject.run(%w(--delay 5)).options.
|
50
|
+
should include(:delay => ['5'])
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does not have a option which given without any arguments." do
|
54
|
+
expect { subject.run(%w(--delay)) }.
|
55
|
+
should raise_error(NotSatisfiedRequirements)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
context "when defined sub-commands" do
|
60
|
+
before do
|
61
|
+
subject.module_eval do
|
62
|
+
def update
|
63
|
+
:update
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
it ".commands is a array of available commands." do
|
69
|
+
subject.commands.should == [:update]
|
70
|
+
end
|
71
|
+
|
72
|
+
it "#dispatch return value which of sub-command's" do
|
73
|
+
subject.new(%w(update)).dispatch.should == subject.new([]).update
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when not defined sub-commands" do
|
78
|
+
it ".commands is empty array." do
|
79
|
+
subject.commands.should be_empty
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
metadata
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gestopft
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.0.1
|
6
|
+
platform: ruby
|
7
|
+
authors: []
|
8
|
+
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-03-18 00:00:00 +09:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description:
|
18
|
+
email: trasty.loose@gmail.com
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions: []
|
22
|
+
|
23
|
+
extra_rdoc_files: []
|
24
|
+
|
25
|
+
files:
|
26
|
+
- README.rdoc
|
27
|
+
- .autotest
|
28
|
+
- .rspec
|
29
|
+
- lib/gestopft/core_ext/array.rb
|
30
|
+
- lib/gestopft/core_ext/symbol.rb
|
31
|
+
- lib/gestopft/core_ext/string.rb
|
32
|
+
- lib/gestopft/app.rb
|
33
|
+
- lib/gestopft/option.rb
|
34
|
+
- lib/gestopft/core_ext.rb
|
35
|
+
- lib/gestopft.rb
|
36
|
+
- spec/gestopft/option_spec.rb
|
37
|
+
- spec/gestopft_spec.rb
|
38
|
+
has_rdoc: true
|
39
|
+
homepage: http://github.com/aereal/gestopft
|
40
|
+
licenses: []
|
41
|
+
|
42
|
+
post_install_message:
|
43
|
+
rdoc_options: []
|
44
|
+
|
45
|
+
require_paths:
|
46
|
+
- lib
|
47
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
48
|
+
none: false
|
49
|
+
requirements:
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: "0"
|
53
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
version: "0"
|
59
|
+
requirements: []
|
60
|
+
|
61
|
+
rubyforge_project:
|
62
|
+
rubygems_version: 1.6.2
|
63
|
+
signing_key:
|
64
|
+
specification_version: 3
|
65
|
+
summary: Framework for CLI Application
|
66
|
+
test_files: []
|
67
|
+
|