doodle 0.0.10 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CREDITS +22 -0
- data/{ChangeLog → History.txt} +22 -3
- data/License.txt +20 -0
- data/Manifest.txt +61 -0
- data/README.txt +166 -0
- data/Rakefile +4 -0
- data/config/hoe.rb +77 -0
- data/config/requirements.rb +15 -0
- data/examples/doodle-errors.rb +25 -0
- data/examples/event-location.rb +3 -7
- data/examples/example-01.rb +1 -1
- data/examples/example-01.rdoc +3 -3
- data/examples/example-02.rb +15 -4
- data/examples/example-02.rdoc +17 -5
- data/examples/mail-datatypes.rb +104 -0
- data/examples/mail.rb +85 -0
- data/examples/parent.rb +40 -0
- data/examples/profile-options.rb +67 -0
- data/examples/smtp_tls.rb +65 -0
- data/examples/test-datatypes.rb +55 -0
- data/examples/yaml-example.rb +40 -0
- data/examples/yaml-example2.rb +42 -0
- data/lib/doodle.rb +364 -301
- data/lib/doodle/datatypes.rb +148 -0
- data/lib/doodle/rfc822.rb +31 -0
- data/lib/doodle/utils.rb +13 -0
- data/lib/doodle/version.rb +9 -0
- data/log/debug.log +0 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/spec/arg_order_spec.rb +5 -5
- data/spec/attributes_spec.rb +66 -24
- data/spec/bugs_spec.rb +109 -6
- data/spec/class_spec.rb +7 -4
- data/spec/class_validation_spec.rb +46 -0
- data/spec/class_var_spec.rb +76 -0
- data/spec/collector_spec.rb +16 -30
- data/spec/conversion_spec.rb +8 -3
- data/spec/defaults_spec.rb +4 -4
- data/spec/doodle_context_spec.rb +3 -4
- data/spec/doodle_spec.rb +25 -15
- data/spec/extra_args_spec.rb +1 -1
- data/spec/factory_spec.rb +3 -3
- data/spec/init_spec.rb +11 -11
- data/spec/new_doodle_spec.rb +19 -0
- data/spec/required_spec.rb +1 -1
- data/spec/serialization_spec.rb +3 -6
- data/spec/singleton_spec.rb +5 -5
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +44 -0
- data/spec/superclass_spec.rb +6 -5
- data/spec/validation2_spec.rb +248 -0
- data/spec/validation_spec.rb +26 -37
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/rspec.rake +21 -0
- data/tasks/website.rake +17 -0
- metadata +76 -20
- data/COPYING +0 -18
- data/README +0 -57
- data/examples/event.rb +0 -39
- data/examples/example-03.rb +0 -45
- data/examples/example-03.rdoc +0 -55
- data/lib/semantic.cache +0 -8
data/examples/example-01.rb
CHANGED
data/examples/example-01.rdoc
CHANGED
@@ -2,7 +2,7 @@ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
|
2
2
|
require 'date'
|
3
3
|
require 'doodle'
|
4
4
|
|
5
|
-
class DateRange < Doodle
|
5
|
+
class DateRange < Doodle
|
6
6
|
has :start_date do
|
7
7
|
default { Date.today }
|
8
8
|
end
|
@@ -12,6 +12,6 @@ class DateRange < Doodle::Base
|
|
12
12
|
end
|
13
13
|
|
14
14
|
dr = DateRange.new
|
15
|
-
dr.start_date # => #<Date:
|
16
|
-
dr.end_date # => #<Date:
|
15
|
+
dr.start_date # => #<Date: 4909159/2,0,2299161>
|
16
|
+
dr.end_date # => #<Date: 4909159/2,0,2299161>
|
17
17
|
|
data/examples/example-02.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
require 'date'
|
3
3
|
require 'doodle'
|
4
|
+
require 'doodle/utils' # for try
|
4
5
|
|
5
|
-
class DateRange < Doodle
|
6
|
+
class DateRange < Doodle
|
6
7
|
has :start_date, :kind => Date do
|
7
8
|
default { Date.today }
|
8
9
|
from String do |s|
|
@@ -25,6 +26,8 @@ class DateRange < Doodle::Base
|
|
25
26
|
m = /(\d{4}-\d{2}-\d{2})\s*(?:to|-|\s)\s*(\d{4}-\d{2}-\d{2})/.match(s)
|
26
27
|
if m
|
27
28
|
self.new(*m.captures)
|
29
|
+
else
|
30
|
+
raise Exception, "Cannot parse date: '#{s}'"
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -57,6 +60,14 @@ dr = DateRange.from '2007-01-01 2007-12-31'
|
|
57
60
|
dr.start_date # =>
|
58
61
|
dr.end_date # =>
|
59
62
|
|
60
|
-
|
61
|
-
dr.
|
62
|
-
dr.
|
63
|
+
p try {
|
64
|
+
dr = DateRange.from 'Hello World'
|
65
|
+
dr.start_date # =>
|
66
|
+
dr.end_date # =>
|
67
|
+
}
|
68
|
+
|
69
|
+
p try {
|
70
|
+
dr = DateRange '2008-01-01', '2007-12-31'
|
71
|
+
dr.start_date # =>
|
72
|
+
dr.end_date # =>
|
73
|
+
}
|
data/examples/example-02.rdoc
CHANGED
@@ -1,8 +1,9 @@
|
|
1
1
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
2
|
require 'date'
|
3
3
|
require 'doodle'
|
4
|
+
require 'doodle/utils' # for try
|
4
5
|
|
5
|
-
class DateRange < Doodle
|
6
|
+
class DateRange < Doodle
|
6
7
|
has :start_date, :kind => Date do
|
7
8
|
default { Date.today }
|
8
9
|
from String do |s|
|
@@ -25,6 +26,8 @@ class DateRange < Doodle::Base
|
|
25
26
|
m = /(\d{4}-\d{2}-\d{2})\s*(?:to|-|\s)\s*(\d{4}-\d{2}-\d{2})/.match(s)
|
26
27
|
if m
|
27
28
|
self.new(*m.captures)
|
29
|
+
else
|
30
|
+
raise Exception, "Cannot parse date: '#{s}'"
|
28
31
|
end
|
29
32
|
end
|
30
33
|
end
|
@@ -57,7 +60,16 @@ dr = DateRange.from '2007-01-01 2007-12-31'
|
|
57
60
|
dr.start_date # => #<Date: 4908203/2,0,2299161>
|
58
61
|
dr.end_date # => #<Date: 4908931/2,0,2299161>
|
59
62
|
|
60
|
-
|
61
|
-
dr.
|
62
|
-
dr.
|
63
|
-
#
|
63
|
+
p try {
|
64
|
+
dr = DateRange.from 'Hello World'
|
65
|
+
dr.start_date # =>
|
66
|
+
dr.end_date # =>
|
67
|
+
}
|
68
|
+
|
69
|
+
p try {
|
70
|
+
dr = DateRange '2008-01-01', '2007-12-31'
|
71
|
+
dr.start_date # =>
|
72
|
+
dr.end_date # =>
|
73
|
+
}
|
74
|
+
# >> #<Doodle::ConversionError: Cannot parse date: 'Hello World'>
|
75
|
+
# >> #<Doodle::ValidationError: DateRange must have end_date >= start_date>
|
@@ -0,0 +1,104 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__), '.'))
|
3
|
+
|
4
|
+
require 'doodle'
|
5
|
+
require 'doodle/datatypes'
|
6
|
+
require 'net/smtp'
|
7
|
+
require 'time'
|
8
|
+
require 'datatypes'
|
9
|
+
require 'smtp_tls'
|
10
|
+
|
11
|
+
# note: translated from Florian Frank's example in dslkit [http://dslkit.rubyforge.org/]
|
12
|
+
|
13
|
+
class Mail < Doodle
|
14
|
+
doodle do
|
15
|
+
string :mail_server, :default => ENV['MAILSERVER'] || 'mail'
|
16
|
+
string :body
|
17
|
+
email :from do
|
18
|
+
default do
|
19
|
+
if ENV['USER']
|
20
|
+
ENV['USER'] + '@' + mail_server
|
21
|
+
else
|
22
|
+
'from@example.com'
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
email :to
|
27
|
+
string :subject, :default => 'Test Email'
|
28
|
+
date :date do
|
29
|
+
default { Time.now.rfc2822 }
|
30
|
+
end
|
31
|
+
string :message_id do
|
32
|
+
default do
|
33
|
+
key = [ ENV['HOSTNAME'] || 'localhost', $$ , Time.now ].join
|
34
|
+
(::Digest::MD5.new << key).to_s
|
35
|
+
end
|
36
|
+
end
|
37
|
+
string :msg do
|
38
|
+
default do
|
39
|
+
[
|
40
|
+
"From: #{from}",
|
41
|
+
"To: #{to}",
|
42
|
+
"Subject: #{subject}",
|
43
|
+
"Date: #{date}",
|
44
|
+
"Message-Id: <#{message_id}@#{mail_server}>",
|
45
|
+
'',
|
46
|
+
body
|
47
|
+
] * "\n"
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def send_message
|
53
|
+
if true
|
54
|
+
puts msg
|
55
|
+
else
|
56
|
+
::Net::SMTP.start(mail_server, 25) do |smtp|
|
57
|
+
smtp.send_message msg, from, to
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
require 'highline/import'
|
64
|
+
def prompt_for_password
|
65
|
+
ask("Enter your password: ") { |q| q.echo = '*' }
|
66
|
+
end
|
67
|
+
|
68
|
+
class GMail < Mail
|
69
|
+
has :mail_server, :default => 'smtp.gmail.com'
|
70
|
+
has :port, :default => 587
|
71
|
+
has :username, :default => 'sean.ohalpin@gmail.com'
|
72
|
+
has :password, :default => 'sesame'
|
73
|
+
# has :password do
|
74
|
+
# init do
|
75
|
+
# prompt_for_password
|
76
|
+
# end
|
77
|
+
# end
|
78
|
+
has :host, :default => 'localhost.localdomain'
|
79
|
+
has :message_format, :default => 'plain'
|
80
|
+
|
81
|
+
def send_message
|
82
|
+
puts msg
|
83
|
+
return
|
84
|
+
::Net::SMTP.start(mail_server,
|
85
|
+
port,
|
86
|
+
host,
|
87
|
+
username,
|
88
|
+
password,
|
89
|
+
message_format) do |smtp|
|
90
|
+
smtp.send_message(msg, from, to)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
GMail do
|
96
|
+
subject subject + ': Hi!'
|
97
|
+
to 'sean.ohalpin@gmail.com'
|
98
|
+
body <<BODY
|
99
|
+
Hi,
|
100
|
+
|
101
|
+
this is a test email from Ruby.
|
102
|
+
|
103
|
+
BODY
|
104
|
+
end.send_message
|
data/examples/mail.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$:.unshift(File.join(File.dirname(__FILE__), '.'))
|
3
|
+
require 'doodle'
|
4
|
+
require 'doodle/rfc822'
|
5
|
+
require 'net/smtp'
|
6
|
+
require 'time'
|
7
|
+
|
8
|
+
# note: translated from Florian Frank's example in dslkit [http://dslkit.rubyforge.org/]
|
9
|
+
|
10
|
+
class Mail < Doodle
|
11
|
+
has :mail_server, :default => ENV['MAILSERVER'] || 'mail'
|
12
|
+
has :body, :kind => String
|
13
|
+
|
14
|
+
has :from, :kind => String do
|
15
|
+
default do
|
16
|
+
if ENV['USER']
|
17
|
+
ENV['USER'] + '@' + mail_server
|
18
|
+
else
|
19
|
+
'from@example.com'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
must 'be valid email address' do |s|
|
23
|
+
s =~ RFC822::EmailAddress
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
has :to, :kind => String do
|
28
|
+
must 'be valid email address' do |s|
|
29
|
+
s =~ RFC822::EmailAddress
|
30
|
+
end
|
31
|
+
end
|
32
|
+
has :subject, :default => 'Test Email'
|
33
|
+
has :date do
|
34
|
+
default { Time.now.rfc2822 }
|
35
|
+
end
|
36
|
+
has :message_id do
|
37
|
+
default do
|
38
|
+
key = [ ENV['HOSTNAME'] || 'localhost', $$ , Time.now ].join
|
39
|
+
(::Digest::MD5.new << key).to_s
|
40
|
+
end
|
41
|
+
end
|
42
|
+
has :msg, :kind => String do
|
43
|
+
default do
|
44
|
+
[
|
45
|
+
"From: #{from}",
|
46
|
+
"To: #{to}",
|
47
|
+
"Subject: #{subject}",
|
48
|
+
"Date: #{date}",
|
49
|
+
"Message-Id: <#{message_id}@#{mail_server}>",
|
50
|
+
'',
|
51
|
+
body
|
52
|
+
] * "\n"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def send
|
57
|
+
if true
|
58
|
+
puts msg
|
59
|
+
else
|
60
|
+
::Net::SMTP.start(mail_server, 25) do |smtp|
|
61
|
+
smtp.send_message msg, from, to
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def mail(&block)
|
68
|
+
Mail.new(&block)
|
69
|
+
end
|
70
|
+
|
71
|
+
def prompt
|
72
|
+
return 'someone@example.com'
|
73
|
+
STDOUT.print "Send to? "
|
74
|
+
STDOUT.flush
|
75
|
+
STDIN.gets.strip
|
76
|
+
end
|
77
|
+
|
78
|
+
m = Mail do
|
79
|
+
subject subject + ': Hi!'
|
80
|
+
if rcpt = prompt
|
81
|
+
to rcpt
|
82
|
+
end
|
83
|
+
body "Hello, world!\n"
|
84
|
+
end
|
85
|
+
m.send
|
data/examples/parent.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
require 'doodle'
|
3
|
+
require 'yaml'
|
4
|
+
|
5
|
+
class Child < Doodle
|
6
|
+
has :name
|
7
|
+
has :dad do
|
8
|
+
# I'm treating block arguments and Proc object (proc/lambda) arguments
|
9
|
+
# to :init differently:
|
10
|
+
# - a proc/lamba is treated as a literal argument, i.e. the
|
11
|
+
# - value is set to a Proc
|
12
|
+
# - a block argument, on the other hand, is instance
|
13
|
+
# - evaluated during initialization
|
14
|
+
# - consequences
|
15
|
+
# - can only be done in init block
|
16
|
+
# - somewhat subtle difference (from programmer's point of
|
17
|
+
# - view) between a proc and a block
|
18
|
+
|
19
|
+
# Also note re: Doodle.parent - its value is only valid
|
20
|
+
# during initialization - this is a way to capture that
|
21
|
+
# value for ues later
|
22
|
+
|
23
|
+
init do
|
24
|
+
parent
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Parent < Child
|
30
|
+
has :children, :collect => Child
|
31
|
+
end
|
32
|
+
|
33
|
+
parent = Parent 'Conn' do
|
34
|
+
child 'Sean'
|
35
|
+
end
|
36
|
+
|
37
|
+
puts parent.to_yaml
|
38
|
+
|
39
|
+
|
40
|
+
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'lib/doodle'
|
2
|
+
|
3
|
+
module CommandLine
|
4
|
+
class Base < Doodle::Base
|
5
|
+
has :name
|
6
|
+
singleton_class do
|
7
|
+
has :doc
|
8
|
+
end
|
9
|
+
def to_s
|
10
|
+
name
|
11
|
+
end
|
12
|
+
end
|
13
|
+
class Command < Base
|
14
|
+
end
|
15
|
+
class KeyValue < Base
|
16
|
+
# specify order (should I need to do this?)
|
17
|
+
has :name
|
18
|
+
has :value
|
19
|
+
def to_s
|
20
|
+
%[--#{name}="#{value}"]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
class Flag < Base
|
24
|
+
def to_s
|
25
|
+
%[--#{name}]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
module Zenity
|
31
|
+
include CommandLine
|
32
|
+
class Entry < Flag
|
33
|
+
# specifying name here has effect of re-ordering positional args
|
34
|
+
doc "Display text entry dialogue"
|
35
|
+
has :name, :default => :entry
|
36
|
+
end
|
37
|
+
class Text < KeyValue
|
38
|
+
doc "Set the dialogue text"
|
39
|
+
has :name, :default => :text
|
40
|
+
end
|
41
|
+
class EntryText < KeyValue
|
42
|
+
doc "Set the entry text"
|
43
|
+
has :name, :default => 'entry-text'
|
44
|
+
end
|
45
|
+
class HideText < KeyValue
|
46
|
+
doc "Hide the entry text"
|
47
|
+
has :name, :default => 'hide-text'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
include Zenity
|
52
|
+
|
53
|
+
1.upto(100) do
|
54
|
+
cmd = [
|
55
|
+
Command.new("zenity"),
|
56
|
+
Entry.new(),
|
57
|
+
# KeyValue.new("text", "Enter name:"),
|
58
|
+
# KeyValue.new(:name => "text", :value => "Enter name:"),
|
59
|
+
# Text.new(:value => "Enter name:"),
|
60
|
+
Text.new(:value => "Enter name:"),
|
61
|
+
EntryText.new(:value => "Enter text"),
|
62
|
+
].join(' ')
|
63
|
+
#puts cmd
|
64
|
+
end
|
65
|
+
#result = `#{cmd}`
|
66
|
+
#puts "result=#{result}"
|
67
|
+
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require "openssl"
|
2
|
+
require "net/smtp"
|
3
|
+
|
4
|
+
Net::SMTP.class_eval do
|
5
|
+
private
|
6
|
+
def do_start(helodomain, user, secret, authtype)
|
7
|
+
raise IOError, 'SMTP session already started' if @started
|
8
|
+
check_auth_args user, secret, authtype if user or secret
|
9
|
+
|
10
|
+
sock = timeout(@open_timeout) { TCPSocket.open(@address, @port) }
|
11
|
+
@socket = Net::InternetMessageIO.new(sock)
|
12
|
+
@socket.read_timeout = 60 #@read_timeout
|
13
|
+
|
14
|
+
check_response(critical { recv_response() })
|
15
|
+
do_helo(helodomain)
|
16
|
+
|
17
|
+
if starttls
|
18
|
+
raise 'openssl library not installed' unless defined?(OpenSSL)
|
19
|
+
ssl = OpenSSL::SSL::SSLSocket.new(sock)
|
20
|
+
ssl.sync_close = true
|
21
|
+
ssl.connect
|
22
|
+
@socket = Net::InternetMessageIO.new(ssl)
|
23
|
+
@socket.read_timeout = 60 #@read_timeout
|
24
|
+
do_helo(helodomain)
|
25
|
+
end
|
26
|
+
|
27
|
+
authenticate user, secret, authtype if user
|
28
|
+
@started = true
|
29
|
+
ensure
|
30
|
+
unless @started
|
31
|
+
# authentication failed, cancel connection.
|
32
|
+
@socket.close if not @started and @socket and not @socket.closed?
|
33
|
+
@socket = nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def do_helo(helodomain)
|
38
|
+
begin
|
39
|
+
if @esmtp
|
40
|
+
ehlo helodomain
|
41
|
+
else
|
42
|
+
helo helodomain
|
43
|
+
end
|
44
|
+
rescue Net::ProtocolError
|
45
|
+
if @esmtp
|
46
|
+
@esmtp = false
|
47
|
+
@error_occured = false
|
48
|
+
retry
|
49
|
+
end
|
50
|
+
raise
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def starttls
|
55
|
+
getok('STARTTLS') rescue return false
|
56
|
+
return true
|
57
|
+
end
|
58
|
+
|
59
|
+
def quit
|
60
|
+
begin
|
61
|
+
getok('QUIT')
|
62
|
+
rescue EOFError
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|