Permalink
Browse files

v4.4.0

  • Loading branch information...
1 parent d79a18b commit ea8d6288a0a13c7feceb93c09446784c56076421 @ahoward committed Nov 25, 2010
Showing with 434 additions and 50 deletions.
  1. +105 −0 README
  2. +79 −1 README.erb
  3. +17 −19 TODO
  4. +2 −1 lib/main.rb
  5. +46 −3 lib/main/cast.rb
  6. +22 −1 lib/main/parameter.rb
  7. +94 −6 lib/main/program/class_methods.rb
  8. +27 −8 lib/main/program/instance_methods.rb
  9. +14 −0 lib/main/util.rb
  10. +2 −2 main.gemspec
  11. +25 −8 samples/j.rb
  12. +1 −1 test/main.rb
View
105 README
@@ -450,13 +450,118 @@ SAMPLES
"forty-two"
+ <========< samples/j.rb >========>
+
+ ~ > cat samples/j.rb
+
+ #!/usr/bin/env ruby
+
+ require 'open-uri'
+
+ require 'main'
+ require 'digest/sha2'
+
+ # you have access to a sequel/amalgalite/sqlite db for free
+ #
+
+ Main {
+ name :i_can_haz_db
+
+ db {
+ create_table(:mp3s) do
+ primary_key :id
+ String :url
+ String :sha
+ end unless table_exists?(:mp3s)
+ }
+
+ def run
+ url = 'http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3'
+ mp3 = open(url){|fd| fd.read}
+ sha = Digest::SHA2.hexdigest(mp3)
+
+ db[:mp3s].insert(:url => url, :sha => sha)
+ p db[:mp3s].all
+ p db
+ end
+ }
+
+ ~ > ruby samples/j.rb
+
+ [{:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>1}, {:url=>"http://s3.amazonaws.com/drawohara.com.mp3/ween-voodoo_lady.mp3", :sha=>"54c99ac7588dcfce1e70540b734805e9c69ff98dcca001e6f2bdec140fb0f9dc", :id=>2}]
+ #<Sequel::Amalgalite::Database: "amalgalite://Users/ahoward/.i_can_haz_db/db.sqlite">
+
+
DOCS
test/main.rb
vim -p lib/main.rb lib/main/*rb
API section below
HISTORY
+ 4.4.0
+ - support for automatic sequel/sqlite/amalgalite dbs for persistent state
+ across invocations
+
+ Main {
+ db {
+ create_table :foo do
+ String key
+ String val
+ end unless table_exists? :foo
+ }
+
+ def run
+ db[:foo].create(:key => 'using', :val => 'amalgalite')
+ end
+ }
+
+ - support for automatic config files with auto populated template data
+
+ Main {
+ config :email => 'your.addy@gmail.com', :password => 'pa$$word'
+
+ def run
+ email = config[:email]
+ end
+ }
+
+ - new paramter types :pathname, :path, :slug, :input, and :output
+
+ - input/output parameters. can be filenames or '-' to supply
+ stdin/stdout respectively
+
+ Main {
+ input :i
+ output :o
+
+ def run
+ i = params[:i].value
+ o = params[:o].value
+
+ line = i.gets
+ o.puts line
+ end
+ }
+
+ - clean up warnings running with 'ruby -w'
+
+ - fix a failing test
+
+ - ability to ignore parameters in sub modes
+
+ Main {
+ argument :foo
+ argument :bar
+
+ def run
+ p param[:bar].value
+ end
+
+ mode :ignoring do
+ params[:foo].ignore!
+ end
+ }
4.0.0
- avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
utilized for testing. this was done to make it simple to wrap
View
@@ -5,9 +5,9 @@ SYNOPSIS
a class factory and dsl for generating command line programs real quick
URI
+ http://github.com/ahoward/main
http://codeforpeople.com/lib/ruby/
http://rubyforge.org/projects/codeforpeople/
- http://github.com/ahoward/main
INSTALL
gem install main
@@ -26,6 +26,8 @@ DESCRIPTION
- parsing user defined ARGV and ENV
- zero requirements for understanding the obtuse apis of *any* command
line option parsers
+ - built-in support for persistent state via sqlite/sequel/amalgalite
+ - built-in support for yaml config files
- leather pants
in short main.rb aims to drastically lower the barrier to writing uniform
@@ -186,6 +188,82 @@ DOCS
API section below
HISTORY
+ 4.4.0
+ - app storage under a dotdir. for example
+
+ Main {
+ name :foobar
+ }
+
+ will have a ~/.foobar/ directory available for storing db/config/etc.
+
+ - support for automatic sequel/sqlite/amalgalite dbs for persistent state
+ across invocations. the db is automatically created under the main
+ programs dotdir (~/.$appname/db.sqlite)
+
+ Main {
+ db {
+ create_table :foo do
+ String key
+ String val
+ end unless table_exists? :foo
+ }
+
+ def run
+ db[:foo].create(:key => 'using', :val => 'amalgalite')
+ end
+ }
+
+ - support for automatic config files with auto populated template data.
+ the first time the program is run the user's editor will be invoked on a
+ config file pre-populate with the same config. subsequent invocations
+ will use the user configured values. the config file is stored at
+ ~/.$appname/config.yml
+
+ Main {
+ config :email => 'your.addy@gmail.com', :password => 'pa$$word'
+
+ def run
+ email = config[:email]
+ end
+ }
+
+ - new paramter types :pathname, :path, :slug, :input, and :output
+
+ - input/output parameters. can be filenames or '-' to supply
+ stdin/stdout respectively
+
+ Main {
+ input :i
+ output :o
+
+ def run
+ i = params[:i].value
+ o = params[:o].value
+
+ line = i.gets
+ o.puts line
+ end
+ }
+
+ - clean up warnings running with 'ruby -w'
+
+ - fix a failing test
+
+ - ability to ignore parameters in sub modes
+
+ Main {
+ argument :foo
+ argument :bar
+
+ def run
+ p param[:bar].value
+ end
+
+ mode :ignoring do
+ params[:foo].ignore!
+ end
+ }
4.0.0
- avoid duping ios. new methods Main.push_ios! and Main.pop_ios! are
utilized for testing. this was done to make it simple to wrap
View
36 TODO
@@ -1,20 +1,18 @@
+todo:
+ - examples of new features
+ - use map.rb
-* support pathname casts
-* support uri casts
-* support filename casts
-* support directory costs
-* support io cast '-' (:input, :output)
-
-* fix weird super bug jeremy found
-
-* figure out how to support '-' ??
-
-* clean up warnings under 'ruby -w'
-* error reporting weird for some errors
-
-===============================================================================
-X calls to abort sometimes lead to STDERR prining twice ;-(
-X main's' with modes, but no run do not operate properly - add default run w/wrap_run!
-X usage fubar when extra chunks are set
-X usage of arguments is fubar when negative arities are used
-X add sanity checks at parameter contruction completion
+done:
+ - clean up warnings under 'ruby -w'
+ - intput/output arguments
+ - support io cast '-' (:input, :output)
+ - slug casts
+ - support uri casts
+ - dotdir support (based on name)
+ - db support
+ - configuration/configfile file support
+ - calls to abort sometimes lead to STDERR prining twice ;-(
+ - main's' with modes, but no run do not operate properly - add default run w/wrap_run!
+ - usage fubar when extra chunks are set
+ - usage of arguments is fubar when negative arities are used
+ - add sanity checks at parameter contruction completion
View
@@ -2,7 +2,7 @@ module Main
#
# top level constants
#
- Main::VERSION = '4.3.0' unless
+ Main::VERSION = '4.4.0' unless
defined? Main::VERSION
def self.version() Main::VERSION end
@@ -13,6 +13,7 @@ def self.libdir() Main::LIBDIR end
Main::EXIT_SUCCESS = 0 unless defined? Main::EXIT_SUCCESS
Main::EXIT_FAILURE = 1 unless defined? Main::EXIT_FAILURE
Main::EXIT_WARN = 42 unless defined? Main::EXIT_WARN
+ Main::EXIT_WARNING = 42 unless defined? Main::EXIT_WARNING
#
# built-in
#
View
@@ -25,7 +25,7 @@ def self.cast m, &b
end
cast :integer do |obj|
- Integer obj
+ Float(obj).to_i
end
cast :float do |obj|
@@ -45,7 +45,7 @@ def self.cast m, &b
end
cast :uri do |obj|
- require 'uri'
+ require 'uri' unless defined?(::URI)
::URI.parse obj.to_s
end
@@ -55,10 +55,53 @@ def self.cast m, &b
end
cast :date do |obj|
- require 'date'
+ require 'date' unless defined?(::Date)
::Date.parse obj.to_s
end
+ cast :pathname do |obj|
+ require 'pathname' unless defined?(::Pathname)
+ Pathname.new(obj.to_s)
+ end
+
+ cast :path do |obj|
+ File.expand_path(obj.to_s)
+ end
+
+ cast :input do |obj|
+ case obj.to_s
+ when '-'
+ io = STDIN.dup
+ io.fattr(:path){ '/dev/stdin' }
+ io
+ else
+ io = open(obj.to_s, 'r+')
+ at_exit{ io.close }
+ io
+ end
+ end
+
+ cast :output do |obj|
+ case obj.to_s
+ when '-'
+ io = STDOUT.dup
+ io.fattr(:path){ '/dev/stdout' }
+ io
+ else
+ io = open(obj.to_s, 'w+')
+ at_exit{ io.close }
+ io
+ end
+ end
+
+ cast :slug do |obj|
+ string = [obj].flatten.compact.join('-')
+ words = string.to_s.scan(%r/\w+/)
+ words.map!{|word| word.gsub %r/[^0-9a-zA-Z_-]/, ''}
+ words.delete_if{|word| word.nil? or word.strip.empty?}
+ String(words.join('-').downcase)
+ end
+
cast :list do |*objs|
[*objs].flatten.join(',').split(/,/)
end
View
@@ -109,10 +109,15 @@ def name
names.first
end
- def default
+ def default(*values)
+ defaults(values) unless values.empty?
defaults.first
end
+ def default=(value)
+ default(value)
+ end
+
def typename
prefix = '--' if type.to_s =~ %r/option/
"#{ type }(#{ prefix }#{ name })"
@@ -248,6 +253,13 @@ def adding_handlers
end
end
+ def remove
+ main.parameters.delete(self)
+ end
+ alias_method('remove!', 'remove')
+ alias_method('ignore', 'remove')
+ alias_method('ignore!', 'ignore')
+
class Argument < Parameter
fattr 'required' => true
@@ -527,6 +539,15 @@ def <<(*a)
delete(*a)
super
end
+
+ def [](*index)
+ first = index.first
+ if(index.size == 1 and (first.is_a?(String) or first.is_a?(Symbol)))
+ first = first.to_s
+ return detect{|param| param.name == first}
+ end
+ return super
+ end
end
class DSL
Oops, something went wrong.

0 comments on commit ea8d628

Please sign in to comment.