gestopft 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,8 @@
1
+ # vim:set ft=ruby:
2
+
3
+ Autotest.add_hook :initialize do |autotest|
4
+ autotest.add_mapping %r{lib/.*\.rb$} do |f, m|
5
+ Dir.glob "spec/**/*.rb"
6
+ end
7
+ end
8
+
data/.rspec ADDED
@@ -0,0 +1,4 @@
1
+ --color
2
+ --format documentation
3
+ --fail-fast
4
+
@@ -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
+
@@ -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
+
@@ -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,10 @@
1
+ # encoding: utf-8
2
+
3
+ require "pathname"
4
+
5
+ dir = Pathname.new(__FILE__).expand_path.parent + 'core_ext/'
6
+
7
+ dir.each_child do |entry|
8
+ require entry.to_s
9
+ end
10
+
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module ArrayExtension
4
+ def option_args
5
+ pos = index('--') ? slice(0...pos) : dup
6
+ end
7
+ end
8
+
9
+ Array.send(:include, ArrayExtension)
10
+
@@ -0,0 +1,14 @@
1
+ # encoding: utf-8
2
+
3
+ module StringExtention
4
+ def option?
5
+ /^--[-a-zA-Z0-9]+$/ === self
6
+ end
7
+
8
+ def to_option
9
+ (slice(0..2) == '--' ? '' : '--') + strip.gsub('_', '-')
10
+ end
11
+ end
12
+
13
+ String.send(:include, StringExtention)
14
+
@@ -0,0 +1,10 @@
1
+ # encoding: utf-8
2
+
3
+ module SymbolExtension
4
+ def to_option
5
+ to_s.to_option
6
+ end
7
+ end
8
+
9
+ Symbol.send(:include, SymbolExtension)
10
+
@@ -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
+