scripting 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Add dependencies to develop your gem here.
4
+ # Include everything needed to run rake, tests, features, etc.
5
+ group :development do
6
+ gem "rspec", ">= 1.0.0"
7
+ gem "jeweler", "~> 1.5.2"
8
+ gem "rcov", ">= 0"
9
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,27 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.1.2)
5
+ git (1.2.5)
6
+ jeweler (1.5.2)
7
+ bundler (~> 1.0.0)
8
+ git (>= 1.2.5)
9
+ rake
10
+ rake (0.8.7)
11
+ rcov (0.9.9)
12
+ rspec (2.5.0)
13
+ rspec-core (~> 2.5.0)
14
+ rspec-expectations (~> 2.5.0)
15
+ rspec-mocks (~> 2.5.0)
16
+ rspec-core (2.5.1)
17
+ rspec-expectations (2.5.0)
18
+ diff-lcs (~> 1.1.2)
19
+ rspec-mocks (2.5.0)
20
+
21
+ PLATFORMS
22
+ ruby
23
+
24
+ DEPENDENCIES
25
+ jeweler (~> 1.5.2)
26
+ rcov
27
+ rspec (>= 1.0.0)
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Scott Deming
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,40 @@
1
+ = Scripting
2
+
3
+ Scripting is a pluggable command line scripting API for Ruby.
4
+
5
+ Writing command line scripts is a process that repeats itself over and over
6
+ again. We deal with command line switches. We deal with maintaining options
7
+ set by the command line switches. Then finally, we perform the desired task.
8
+
9
+ Time to simplify.
10
+
11
+ By default Scripting provides the general tools needed to write command line
12
+ scripts quickly and easily. The default parsing mechanics are provided by
13
+ optparse. Options are maintained in an object that allows maximum flexibility
14
+ while easing the pain of deailing with hash names (is the key a symbol or a
15
+ string?). Options can be blocks that update other options, return an object
16
+ instance, or they can be simple primitive values like true and false, 0, or
17
+ a string.
18
+
19
+ The overall goal of Scripting is to provide an easy to read and write DSL
20
+ that makes writing command line scripts more tolerable.
21
+
22
+ == Example
23
+
24
+ See examples/
25
+
26
+ == Contributing to scripting
27
+
28
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
29
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
30
+ * Fork the project
31
+ * Start a feature/bugfix branch
32
+ * Commit and push until you are happy with your contribution
33
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
34
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
35
+
36
+ == Copyright
37
+
38
+ Copyright (c) 2011 Scott Deming. See LICENSE.txt for
39
+ further details.
40
+
data/Rakefile ADDED
@@ -0,0 +1,50 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
15
+ gem.name = "scripting"
16
+ gem.homepage = "http://github.com/sdeming/scripting"
17
+ gem.license = "MIT"
18
+ gem.summary = %Q{Simplified command line scripting tool}
19
+ gem.description = %Q{Simplified command line scripting tool}
20
+ gem.email = "sdeming@makefile.com"
21
+ gem.authors = ["sdeming"]
22
+ # Include your dependencies below. Runtime dependencies are required when using your gem,
23
+ # and development dependencies are only needed for development (ie running rake tasks, tests, etc)
24
+ # gem.add_runtime_dependency 'jabber4r', '> 0.1'
25
+ # gem.add_development_dependency 'rspec', '> 1.2.3'
26
+ end
27
+ Jeweler::RubygemsDotOrgTasks.new
28
+
29
+ require 'rspec/core'
30
+ require 'rspec/core/rake_task'
31
+ RSpec::Core::RakeTask.new(:spec) do |spec|
32
+ spec.pattern = FileList['spec/**/*_spec.rb']
33
+ end
34
+
35
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
36
+ spec.pattern = 'spec/**/*_spec.rb'
37
+ spec.rcov = true
38
+ end
39
+
40
+ task :default => :spec
41
+
42
+ require 'rake/rdoctask'
43
+ Rake::RDocTask.new do |rdoc|
44
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
45
+
46
+ rdoc.rdoc_dir = 'rdoc'
47
+ rdoc.title = "scripting #{version}"
48
+ rdoc.rdoc_files.include('README*')
49
+ rdoc.rdoc_files.include('lib/**/*.rb')
50
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
@@ -0,0 +1,34 @@
1
+ require File.expand_path('../../lib/scripting', __FILE__)
2
+
3
+ MyApp = Scripting::create_application do
4
+ plugin Scripting::AppDefaults
5
+ uses :default_switches
6
+ uses :default_options
7
+
8
+ options do
9
+ message { "Hello World" }
10
+ stdout false
11
+ stderr false
12
+ end
13
+
14
+ switches do
15
+ on('-o', '--[no-]stdout', "Write message to STDOUT") do |opt|
16
+ options.stdout = opt
17
+ end
18
+
19
+ on('-e', '--[no-]stderr', "Write message to STDERR") do |opt|
20
+ options.stderr = opt
21
+ end
22
+
23
+ on('-m', '--message=TEXT', "Message to write") do |opt|
24
+ options.message = opt
25
+ end
26
+ end
27
+
28
+ work do
29
+ STDERR.puts options.message if options.stderr
30
+ STDOUT.puts options.message if options.stdout
31
+ end
32
+ end
33
+
34
+ MyApp.run! ARGV
@@ -0,0 +1,34 @@
1
+ module Scripting
2
+ module AppDefaults
3
+
4
+ def self.included(base)
5
+ base.class_eval do
6
+ plugins :default_switches, :default_options
7
+ end
8
+ end
9
+
10
+ def default_options(context)
11
+ context.describe do
12
+ options do
13
+ verbose false
14
+ end
15
+ end
16
+ end
17
+
18
+ def default_switches(context)
19
+ context.describe do
20
+ switches do
21
+ on_tail('-v', '--verbose', 'Enable verbose output') do
22
+ options.verbose = true
23
+ end
24
+
25
+ on_tail('-h', '--help', "Help text") do
26
+ puts self
27
+ terminate
28
+ end
29
+ end
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,74 @@
1
+ require File.expand_path('../pluggable', __FILE__)
2
+ require File.expand_path('../parser', __FILE__)
3
+ require File.expand_path('../options', __FILE__)
4
+ require File.expand_path('../app_defaults', __FILE__)
5
+
6
+ module Scripting
7
+ class Application
8
+ extend Pluggable
9
+
10
+ def initialize
11
+ @options = Options.new
12
+ @switches = Parser.new(self)
13
+ @work = []
14
+ end
15
+
16
+ def context
17
+ self
18
+ end
19
+
20
+ def describe &blk
21
+ instance_eval &blk if block_given?
22
+ self
23
+ end
24
+
25
+ def switches &blk
26
+ @switches.instance_eval &blk if block_given?
27
+ @switches
28
+ end
29
+
30
+ def options &blk
31
+ @options.describe &blk if block_given?
32
+ @options
33
+ end
34
+
35
+ def work &blk
36
+ @work << blk if block_given?
37
+ @work
38
+ end
39
+
40
+ def plugin module_name
41
+ self.class.send(:include, module_name)
42
+ end
43
+
44
+ def uses *names
45
+ names.each do |name|
46
+ name = name.to_sym
47
+ if installed_plugins.include? name
48
+ send(name, self)
49
+ else
50
+ raise "unknown method '#{name.inspect}' provided in uses"
51
+ end
52
+ end
53
+ end
54
+
55
+ def parse! args
56
+ switches.parse! args
57
+ args
58
+ end
59
+
60
+ def run! *args
61
+ if args.first.kind_of? Array
62
+ args.flatten!
63
+ end
64
+ parse! args
65
+ work.each { |work| instance_exec(*args, &work) }
66
+ end
67
+ end
68
+
69
+ def self.create_application &blk
70
+ app = Application.new
71
+ app.describe &blk
72
+ app
73
+ end
74
+ end
@@ -0,0 +1,35 @@
1
+ module Scripting
2
+
3
+ class Options
4
+ def describe &blk; instance_eval &blk; end
5
+
6
+ def [](name)
7
+ ivar = "@#{name}"
8
+ value = instance_variable_get(ivar)
9
+
10
+ if value.respond_to? :call
11
+ instance_eval &value
12
+ else
13
+ value
14
+ end
15
+ end
16
+
17
+ def []=(name, value)
18
+ ivar = "@#{name}"
19
+ instance_variable_set(ivar, value)
20
+ end
21
+
22
+ def method_missing(name, value = nil, &blk)
23
+ name = name.to_s
24
+ name = name[0..-2] if name =~ /=$/
25
+
26
+ if block_given?
27
+ self[name] = blk
28
+ elsif !value.nil?
29
+ self[name] = value
30
+ else
31
+ self[name]
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,24 @@
1
+ require 'forwardable'
2
+ require 'delegate'
3
+ require 'optparse'
4
+
5
+ module Scripting
6
+ #TODO: flesh this out... We can, ideally, use any options parser but by default we use optparse.
7
+ def self.CustomParser(klass)
8
+ custom = Class.new(DelegateClass(klass))
9
+ custom.class_eval do
10
+ extend(Forwardable)
11
+ def_delegators :@context, :context, :options
12
+ def describe; instance_eval; end
13
+ end
14
+
15
+ custom.send(:define_method, :initialize) do |context|
16
+ @context = context
17
+ super(klass.new)
18
+ end
19
+
20
+ custom
21
+ end
22
+
23
+ Parser = Scripting::CustomParser(OptionParser)
24
+ end
@@ -0,0 +1,35 @@
1
+ module Scripting
2
+ module Pluggable
3
+ module ClassMethods
4
+ def meta
5
+ (class << self; self; end)
6
+ end
7
+
8
+ def plugin name
9
+ plugins = self.meta.instance_variable_get("@__plugins__")
10
+ plugins << name
11
+ self.meta.instance_variable_set("@__plugins__", plugins)
12
+ end
13
+
14
+ def plugins *names
15
+ names.each { |name| self.plugin(name) }
16
+ self.meta.instance_variable_get("@__plugins__")
17
+ end
18
+
19
+ def self.extended(base)
20
+ base.meta.instance_variable_set("@__plugins__", [])
21
+ end
22
+ end
23
+
24
+ module InstanceMethods
25
+ def installed_plugins
26
+ self.class.plugins
27
+ end
28
+ end
29
+
30
+ def self.extended(base)
31
+ base.send(:extend, ClassMethods)
32
+ base.send(:include, InstanceMethods)
33
+ end
34
+ end
35
+ end
data/lib/scripting.rb ADDED
@@ -0,0 +1 @@
1
+ require File.expand_path('../scripting/application', __FILE__)
data/scripting.gemspec ADDED
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{scripting}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["sdeming"]
12
+ s.date = %q{2011-03-06}
13
+ s.description = %q{Simplified command line scripting tool}
14
+ s.email = %q{sdeming@makefile.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE.txt",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
22
+ "LICENSE.txt",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "examples/simple.rb",
27
+ "lib/scripting.rb",
28
+ "lib/scripting/app_defaults.rb",
29
+ "lib/scripting/application.rb",
30
+ "lib/scripting/options.rb",
31
+ "lib/scripting/parser.rb",
32
+ "lib/scripting/pluggable.rb",
33
+ "scripting.gemspec",
34
+ "spec/application_spec.rb",
35
+ "spec/options_spec.rb",
36
+ "spec/spec_helper.rb"
37
+ ]
38
+ s.homepage = %q{http://github.com/sdeming/scripting}
39
+ s.licenses = ["MIT"]
40
+ s.require_paths = ["lib"]
41
+ s.rubygems_version = %q{1.3.7}
42
+ s.summary = %q{Simplified command line scripting tool}
43
+ s.test_files = [
44
+ "examples/simple.rb",
45
+ "spec/application_spec.rb",
46
+ "spec/options_spec.rb",
47
+ "spec/spec_helper.rb"
48
+ ]
49
+
50
+ if s.respond_to? :specification_version then
51
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<rspec>, [">= 1.0.0"])
56
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
57
+ s.add_development_dependency(%q<rcov>, [">= 0"])
58
+ else
59
+ s.add_dependency(%q<rspec>, [">= 1.0.0"])
60
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
61
+ s.add_dependency(%q<rcov>, [">= 0"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<rspec>, [">= 1.0.0"])
65
+ s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
66
+ s.add_dependency(%q<rcov>, [">= 0"])
67
+ end
68
+ end
69
+
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ describe Scripting::Application do
4
+
5
+ it "should run a work block" do
6
+ app = Scripting::create_application do
7
+ work { options.work1_ran = true }
8
+ end
9
+
10
+ app.options.work1_ran.should be_nil
11
+ app.run!
12
+ app.options.work1_ran.should be_true
13
+ end
14
+
15
+ it "should run many work blocks in order" do
16
+ app = Scripting::create_application do
17
+ work { options.work_runs = [1] }
18
+ work { options.work_runs.push 2 }
19
+ work { options.work_runs.push 3 }
20
+ end
21
+
22
+ app.options.work_runs.should be_nil
23
+ app.run!
24
+ app.options.work_runs.should == [1,2,3]
25
+ end
26
+
27
+ it "should pass extra args to work blocks" do
28
+ app = Scripting::create_application do
29
+ work do |*extra_args|
30
+ action = extra_args.first
31
+ options.action = action
32
+ end
33
+ end
34
+
35
+ app.options.action.should be_nil
36
+ app.run! ["digest"]
37
+ app.options.action.should == "digest"
38
+ end
39
+
40
+ it "should define default options when using AppDefaults plugin" do
41
+ app = Scripting::create_application do
42
+ plugin Scripting::AppDefaults
43
+ uses :default_options
44
+ end
45
+ app.options.verbose.should be_false
46
+ end
47
+
48
+ it "should define default switches when using AppDefaults plugin" do
49
+ app = Scripting::create_application do
50
+ plugin Scripting::AppDefaults
51
+ uses :default_switches
52
+ end
53
+ app.options.verbose.should be_nil
54
+ app.parse! ["-v"]
55
+ app.options.verbose.should be_true
56
+ end
57
+
58
+ it "should define both default options and switches when using AppDefaults plugin" do
59
+ app1 = Scripting::create_application do
60
+ plugin Scripting::AppDefaults
61
+ uses :default_switches
62
+ uses :default_options
63
+ end
64
+ app1.options.verbose.should be_false
65
+ app1.parse! ["-v"]
66
+ app1.options.verbose.should be_true
67
+
68
+ app2 = Scripting::create_application do
69
+ plugin Scripting::AppDefaults
70
+ uses :default_switches, :default_options
71
+ end
72
+ app2.options.verbose.should be_false
73
+ app2.parse! ["-v"]
74
+ app2.options.verbose.should be_true
75
+ end
76
+ end
@@ -0,0 +1,53 @@
1
+ require 'spec_helper'
2
+
3
+ describe Scripting::Options do
4
+
5
+ it "should assign without =" do
6
+ opts = Scripting::Options.new
7
+ opts.first :a
8
+ opts.second :b
9
+
10
+ opts.first.should == :a
11
+ opts.second.should == :b
12
+ end
13
+
14
+ it "should assign with =" do
15
+ opts = Scripting::Options.new
16
+ opts.first = :a
17
+ opts.second = :b
18
+ opts.third = 3
19
+
20
+ opts.first.should == :a
21
+ opts.second.should == :b
22
+ opts.third.should == 3
23
+ end
24
+
25
+ it "should assign with or without =" do
26
+ opts = Scripting::Options.new
27
+ opts.first = :a
28
+ opts.second :b
29
+ opts.third = 3
30
+ opts.fourth "4"
31
+
32
+ opts.first.should == :a
33
+ opts.second.should == :b
34
+ opts.third.should == 3
35
+ opts.fourth.should == "4"
36
+ end
37
+
38
+ it "should assign blocks and call for each visit" do
39
+ opts = Scripting::Options.new
40
+ opts.block { true }
41
+ opts.block.should be_true
42
+ end
43
+
44
+ it "should assign blocks and invoke them in the scope of the entire options instance" do
45
+ opts = Scripting::Options.new
46
+ opts.count 0
47
+ opts.block { self.count += 1 }
48
+
49
+ opts.block.should == 1
50
+ opts.block.should == 2
51
+ end
52
+
53
+ end
@@ -0,0 +1 @@
1
+ require File.expand_path("../../lib/scripting", __FILE__)
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: scripting
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 1
8
+ - 0
9
+ version: 0.1.0
10
+ platform: ruby
11
+ authors:
12
+ - sdeming
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-03-06 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: rspec
22
+ requirement: &id001 !ruby/object:Gem::Requirement
23
+ none: false
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 1
29
+ - 0
30
+ - 0
31
+ version: 1.0.0
32
+ type: :development
33
+ prerelease: false
34
+ version_requirements: *id001
35
+ - !ruby/object:Gem::Dependency
36
+ name: jeweler
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ~>
41
+ - !ruby/object:Gem::Version
42
+ segments:
43
+ - 1
44
+ - 5
45
+ - 2
46
+ version: 1.5.2
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: *id002
50
+ - !ruby/object:Gem::Dependency
51
+ name: rcov
52
+ requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ">="
56
+ - !ruby/object:Gem::Version
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ prerelease: false
62
+ version_requirements: *id003
63
+ description: Simplified command line scripting tool
64
+ email: sdeming@makefile.com
65
+ executables: []
66
+
67
+ extensions: []
68
+
69
+ extra_rdoc_files:
70
+ - LICENSE.txt
71
+ - README.rdoc
72
+ files:
73
+ - Gemfile
74
+ - Gemfile.lock
75
+ - LICENSE.txt
76
+ - README.rdoc
77
+ - Rakefile
78
+ - VERSION
79
+ - examples/simple.rb
80
+ - lib/scripting.rb
81
+ - lib/scripting/app_defaults.rb
82
+ - lib/scripting/application.rb
83
+ - lib/scripting/options.rb
84
+ - lib/scripting/parser.rb
85
+ - lib/scripting/pluggable.rb
86
+ - scripting.gemspec
87
+ - spec/application_spec.rb
88
+ - spec/options_spec.rb
89
+ - spec/spec_helper.rb
90
+ has_rdoc: true
91
+ homepage: http://github.com/sdeming/scripting
92
+ licenses:
93
+ - MIT
94
+ post_install_message:
95
+ rdoc_options: []
96
+
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ none: false
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ hash: 1339519597396043880
105
+ segments:
106
+ - 0
107
+ version: "0"
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ none: false
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ segments:
114
+ - 0
115
+ version: "0"
116
+ requirements: []
117
+
118
+ rubyforge_project:
119
+ rubygems_version: 1.3.7
120
+ signing_key:
121
+ specification_version: 3
122
+ summary: Simplified command line scripting tool
123
+ test_files:
124
+ - examples/simple.rb
125
+ - spec/application_spec.rb
126
+ - spec/options_spec.rb
127
+ - spec/spec_helper.rb