butler 1.8.0

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.
Files changed (164) hide show
  1. data/CHANGELOG +4 -0
  2. data/GPL.txt +340 -0
  3. data/LICENSE.txt +52 -0
  4. data/README +37 -0
  5. data/Rakefile +334 -0
  6. data/bin/botcontrol +230 -0
  7. data/data/butler/config_template.yaml +4 -0
  8. data/data/butler/dialogs/backup.rb +19 -0
  9. data/data/butler/dialogs/botcontrol.rb +4 -0
  10. data/data/butler/dialogs/config.rb +1 -0
  11. data/data/butler/dialogs/create.rb +53 -0
  12. data/data/butler/dialogs/delete.rb +3 -0
  13. data/data/butler/dialogs/en/backup.yaml +6 -0
  14. data/data/butler/dialogs/en/botcontrol.yaml +5 -0
  15. data/data/butler/dialogs/en/create.yaml +11 -0
  16. data/data/butler/dialogs/en/delete.yaml +2 -0
  17. data/data/butler/dialogs/en/help.yaml +17 -0
  18. data/data/butler/dialogs/en/info.yaml +13 -0
  19. data/data/butler/dialogs/en/list.yaml +4 -0
  20. data/data/butler/dialogs/en/notyetimplemented.yaml +2 -0
  21. data/data/butler/dialogs/en/rename.yaml +3 -0
  22. data/data/butler/dialogs/en/start.yaml +3 -0
  23. data/data/butler/dialogs/en/sync_plugins.yaml +3 -0
  24. data/data/butler/dialogs/en/uninstall.yaml +5 -0
  25. data/data/butler/dialogs/en/unknown_command.yaml +2 -0
  26. data/data/butler/dialogs/help.rb +11 -0
  27. data/data/butler/dialogs/info.rb +27 -0
  28. data/data/butler/dialogs/interactive.rb +1 -0
  29. data/data/butler/dialogs/list.rb +10 -0
  30. data/data/butler/dialogs/notyetimplemented.rb +1 -0
  31. data/data/butler/dialogs/rename.rb +4 -0
  32. data/data/butler/dialogs/selectbot.rb +2 -0
  33. data/data/butler/dialogs/start.rb +5 -0
  34. data/data/butler/dialogs/sync_plugins.rb +30 -0
  35. data/data/butler/dialogs/uninstall.rb +17 -0
  36. data/data/butler/dialogs/unknown_command.rb +1 -0
  37. data/data/butler/plugins/core/logout.rb +41 -0
  38. data/data/butler/plugins/core/plugins.rb +134 -0
  39. data/data/butler/plugins/core/privilege.rb +103 -0
  40. data/data/butler/plugins/core/user.rb +166 -0
  41. data/data/butler/plugins/dev/eval.rb +64 -0
  42. data/data/butler/plugins/dev/nometa.rb +14 -0
  43. data/data/butler/plugins/dev/onhandlers.rb +93 -0
  44. data/data/butler/plugins/dev/raw.rb +36 -0
  45. data/data/butler/plugins/dev/rawlog.rb +77 -0
  46. data/data/butler/plugins/games/eightball.rb +54 -0
  47. data/data/butler/plugins/games/mastermind.rb +174 -0
  48. data/data/butler/plugins/irc/action.rb +36 -0
  49. data/data/butler/plugins/irc/join.rb +38 -0
  50. data/data/butler/plugins/irc/notice.rb +36 -0
  51. data/data/butler/plugins/irc/part.rb +38 -0
  52. data/data/butler/plugins/irc/privmsg.rb +36 -0
  53. data/data/butler/plugins/irc/quit.rb +36 -0
  54. data/data/butler/plugins/operator/deop.rb +41 -0
  55. data/data/butler/plugins/operator/devoice.rb +41 -0
  56. data/data/butler/plugins/operator/limit.rb +47 -0
  57. data/data/butler/plugins/operator/op.rb +41 -0
  58. data/data/butler/plugins/operator/voice.rb +41 -0
  59. data/data/butler/plugins/public/help.rb +69 -0
  60. data/data/butler/plugins/public/login.rb +72 -0
  61. data/data/butler/plugins/public/usage.rb +49 -0
  62. data/data/butler/plugins/service/clones.rb +56 -0
  63. data/data/butler/plugins/service/define.rb +47 -0
  64. data/data/butler/plugins/service/log.rb +183 -0
  65. data/data/butler/plugins/service/svn.rb +91 -0
  66. data/data/butler/plugins/util/cycle.rb +98 -0
  67. data/data/butler/plugins/util/load.rb +41 -0
  68. data/data/butler/plugins/util/pong.rb +29 -0
  69. data/data/butler/strings/random/acknowledge.en.yaml +5 -0
  70. data/data/butler/strings/random/gratitude.en.yaml +3 -0
  71. data/data/butler/strings/random/hello.en.yaml +4 -0
  72. data/data/butler/strings/random/ignorance.en.yaml +7 -0
  73. data/data/butler/strings/random/ignorance_about.en.yaml +3 -0
  74. data/data/butler/strings/random/insult.en.yaml +3 -0
  75. data/data/butler/strings/random/rejection.en.yaml +12 -0
  76. data/data/man/botcontrol.1 +17 -0
  77. data/lib/access.rb +187 -0
  78. data/lib/access/admin.rb +16 -0
  79. data/lib/access/privilege.rb +122 -0
  80. data/lib/access/role.rb +102 -0
  81. data/lib/access/savable.rb +18 -0
  82. data/lib/access/user.rb +180 -0
  83. data/lib/access/yamlbase.rb +126 -0
  84. data/lib/butler.rb +188 -0
  85. data/lib/butler/bot.rb +247 -0
  86. data/lib/butler/control.rb +93 -0
  87. data/lib/butler/dialog.rb +64 -0
  88. data/lib/butler/initialvalues.rb +40 -0
  89. data/lib/butler/irc/channel.rb +135 -0
  90. data/lib/butler/irc/channels.rb +96 -0
  91. data/lib/butler/irc/client.rb +351 -0
  92. data/lib/butler/irc/hostmask.rb +53 -0
  93. data/lib/butler/irc/message.rb +184 -0
  94. data/lib/butler/irc/parser.rb +125 -0
  95. data/lib/butler/irc/parser/commands.rb +83 -0
  96. data/lib/butler/irc/parser/generic.rb +343 -0
  97. data/lib/butler/irc/socket.rb +378 -0
  98. data/lib/butler/irc/string.rb +186 -0
  99. data/lib/butler/irc/topic.rb +15 -0
  100. data/lib/butler/irc/user.rb +265 -0
  101. data/lib/butler/irc/users.rb +112 -0
  102. data/lib/butler/plugin.rb +249 -0
  103. data/lib/butler/plugin/configproxy.rb +35 -0
  104. data/lib/butler/plugin/mapper.rb +85 -0
  105. data/lib/butler/plugin/matcher.rb +55 -0
  106. data/lib/butler/plugin/onhandlers.rb +70 -0
  107. data/lib/butler/plugin/trigger.rb +58 -0
  108. data/lib/butler/plugins.rb +147 -0
  109. data/lib/butler/version.rb +17 -0
  110. data/lib/cloptions.rb +217 -0
  111. data/lib/cloptions/adapters.rb +24 -0
  112. data/lib/cloptions/switch.rb +132 -0
  113. data/lib/configuration.rb +223 -0
  114. data/lib/dialogline.rb +296 -0
  115. data/lib/dialogline/localizations.rb +24 -0
  116. data/lib/durations.rb +57 -0
  117. data/lib/event.rb +295 -0
  118. data/lib/event/at.rb +64 -0
  119. data/lib/event/every.rb +56 -0
  120. data/lib/event/timed.rb +112 -0
  121. data/lib/installer.rb +75 -0
  122. data/lib/iterator.rb +34 -0
  123. data/lib/log.rb +68 -0
  124. data/lib/log/comfort.rb +85 -0
  125. data/lib/log/converter.rb +23 -0
  126. data/lib/log/entry.rb +152 -0
  127. data/lib/log/fakeio.rb +55 -0
  128. data/lib/log/file.rb +54 -0
  129. data/lib/log/filereader.rb +81 -0
  130. data/lib/log/forward.rb +49 -0
  131. data/lib/log/methods.rb +39 -0
  132. data/lib/log/nolog.rb +18 -0
  133. data/lib/log/splitter.rb +26 -0
  134. data/lib/ostructfixed.rb +26 -0
  135. data/lib/ruby/array/columnize.rb +38 -0
  136. data/lib/ruby/dir/mktree.rb +28 -0
  137. data/lib/ruby/enumerable/join.rb +13 -0
  138. data/lib/ruby/exception/detailed.rb +24 -0
  139. data/lib/ruby/file/append.rb +11 -0
  140. data/lib/ruby/file/write.rb +11 -0
  141. data/lib/ruby/hash/zip.rb +15 -0
  142. data/lib/ruby/kernel/bench.rb +15 -0
  143. data/lib/ruby/kernel/daemonize.rb +42 -0
  144. data/lib/ruby/kernel/non_verbose.rb +17 -0
  145. data/lib/ruby/kernel/safe_fork.rb +18 -0
  146. data/lib/ruby/range/stepped.rb +11 -0
  147. data/lib/ruby/string/arguments.rb +72 -0
  148. data/lib/ruby/string/chunks.rb +15 -0
  149. data/lib/ruby/string/post_arguments.rb +44 -0
  150. data/lib/ruby/string/unescaped.rb +17 -0
  151. data/lib/scheduler.rb +164 -0
  152. data/lib/scriptfile.rb +101 -0
  153. data/lib/templater.rb +86 -0
  154. data/test/cloptions.rb +134 -0
  155. data/test/cv.rb +28 -0
  156. data/test/irc/client.rb +85 -0
  157. data/test/irc/client_login.txt +53 -0
  158. data/test/irc/client_subscribe.txt +8 -0
  159. data/test/irc/message.rb +30 -0
  160. data/test/irc/messages.txt +64 -0
  161. data/test/irc/parser.rb +13 -0
  162. data/test/irc/profile_parser.rb +12 -0
  163. data/test/irc/users.rb +28 -0
  164. metadata +256 -0
@@ -0,0 +1,17 @@
1
+ class String
2
+ # convert \" to " and similar
3
+ Escapes = Hash.new{|h,k|k}.update({
4
+ '\\\\' => '\\',
5
+ '\\"' => '"',
6
+ "\\'" => "'",
7
+ '\e' => "\e",
8
+ '\r' => "\r",
9
+ '\n' => "\n",
10
+ '\f' => "\f",
11
+ '\t' => "\t",
12
+ '\ ' => " ",
13
+ })
14
+ def unescaped
15
+ gsub(/\\.|[^\\]/) { |m| Escapes[m] }
16
+ end
17
+ end
@@ -0,0 +1,164 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'durations'
10
+ require 'event'
11
+ require 'thread'
12
+ require 'log/comfort'
13
+
14
+
15
+
16
+ # == Synopsis
17
+ # scheduler = Dispatcher::Scheduled.new(*events)
18
+ # scheduler.every 5.minutes do puts "Another 5 minutes wasted!" end
19
+ # scheduler.add(event)
20
+ # scheduler.delete(event)
21
+ # scheduler.suspend
22
+ # scheduler.resume
23
+ # scheduler.terminate # important, else you'll have a forever sleeping thread left
24
+ #
25
+ # == Description
26
+ # Provides methods to execute scheduled Events
27
+ #
28
+ class Scheduler
29
+ include Log::Comfort
30
+
31
+ def initialize(delete_finished=true, *events)
32
+ events.each { |event| event.scheduler = self }
33
+ @terminated = false
34
+ @instructions = Queue.new
35
+ @mutex = Mutex.new
36
+ @events = []
37
+ @alarm = Thread.new {} # dead thread
38
+ @min_sleep = 0.1
39
+ @execute = method(:execute)
40
+ @sleeper = Thread.new(&method(:sleeper))
41
+ @auto_delete = delete_finished
42
+ add(*events)
43
+ end
44
+
45
+ def sleeper
46
+ while instr = @instructions.shift
47
+ @alarm.kill # just overkill...
48
+
49
+ now = Time.now+@min_sleep
50
+ @mutex.synchronize {
51
+ i = nil
52
+ @events.each_with_index { |event,i|
53
+ break unless event.due?(now)
54
+ event.one_done
55
+ Thread.new(event, &@execute)
56
+ }
57
+ @events.first(i+1).each { |event|
58
+ @events.delete(event) if event.finished?
59
+ } if (@auto_delete && i)
60
+ unless @events.empty?
61
+ @events.sort!
62
+ if seconds = @events.first.seconds_left then
63
+ if seconds < @min_sleep then
64
+ @instructions.push(:wakeup)
65
+ else
66
+ @alarm = Thread.new {
67
+ sleep(seconds)
68
+ @instructions.push(:wakeup)
69
+ }
70
+ end
71
+ end
72
+ end
73
+ }
74
+ end
75
+ end
76
+
77
+ # not yet implemented
78
+ def suspend
79
+ end
80
+
81
+ # not yet implemented
82
+ def resume
83
+ end
84
+
85
+ # not yet implemented
86
+ def restart
87
+ end
88
+
89
+ def terminate
90
+ end
91
+
92
+ def reschedule(event)
93
+ @mutex.synchronize {
94
+ #first = @events.first
95
+ @events.sort!
96
+ #first != @events.first
97
+ }
98
+ @instructions.push(:reschedule)
99
+ self
100
+ end
101
+
102
+ # Adds the events to the scheduler
103
+ def add(*events)
104
+ events.each { |event| event.scheduler = self }
105
+ @instructions.push(:reschedule) if @mutex.synchronize {
106
+ first = @events.first
107
+ @events.push(*events)
108
+ @events.sort!
109
+ first != @events.first
110
+ }
111
+ self
112
+ end
113
+ alias << add
114
+
115
+ def delete(event)
116
+ wakeup = false
117
+ @mutex.synchronize {
118
+ wakeup = @events.first == event
119
+ @events.delete(event)
120
+ }
121
+ @instructions.push(:reschedule) if wakeup
122
+ end
123
+
124
+ def reject!(&block)
125
+ @instructions.push(:reschedule) if @mutex.synchronize {
126
+ first = @events.first
127
+ @events.reject!(&block)
128
+ @events.min
129
+ first != @events.first
130
+ }
131
+ end
132
+
133
+ def execute(event)
134
+ event.call(event)
135
+ rescue Exception => e
136
+ exception(e) # log it
137
+ end
138
+
139
+ # Creates a new Dispatcher::Event.every, adds it and
140
+ # returns the event
141
+ def every(*args, &block)
142
+ add(event = Event::Every.new(*args, &block))
143
+ event
144
+ end
145
+
146
+ # Creates a new Dispatcher::Event.timed, adds it and
147
+ # returns the event
148
+ def timed(*args, &block)
149
+ add(event = Event::Timed.new(*args, &block))
150
+ event
151
+ end
152
+
153
+ # Creates a new Dispatcher::Event.timed, adds it and
154
+ # returns the event
155
+ def at(*args, &block)
156
+ add(event = Event::At.new(*args, &block))
157
+ event
158
+ end
159
+
160
+ # The amount of scheduled events
161
+ def length
162
+ @events.length
163
+ end
164
+ end
@@ -0,0 +1,101 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'ruby/kernel/non_verbose'
10
+
11
+ # use data after __END__ in .rb files like normal files
12
+ # WARNING:
13
+ # - if you have an __END__ alone in a multiline comment or string
14
+ # your .rb file will be damaged.
15
+ # - Current implementation *will* append an __END__ to the file, regardeless
16
+ #  of what you do (that will change)
17
+ #
18
+ # Example:
19
+ # require 'scriptfile'
20
+ # ScriptFile.open(__FILE__) { |fh|
21
+ # p [:tell, fh.tell]
22
+ # p [:read, fh.read]
23
+ # p [:tell, fh.tell]
24
+ # p [:truncate, fh.truncate]
25
+ # p [:tell, fh.tell]
26
+ # p [:read, fh.read]
27
+ # p [:tell, fh.tell]
28
+ # p [:seek, fh.seek]
29
+ # p [:puts, fh.puts("ScriptFile rocks")]
30
+ # p [:seek, fh.seek]
31
+ # p [:read, fh.read]
32
+ # }
33
+ #
34
+ class ScriptFile < File
35
+ (IO.instance_methods(false)+File.instance_methods(false) - %w[see tell pos truncate]).each { |m| private m }
36
+
37
+ class <<self
38
+ def read(file)
39
+ open(file) { |fh| fh.read }
40
+ end
41
+
42
+ def open(file, mode="r")
43
+ fh = new(file, mode)
44
+ block_given? ? yield(fh) : fh
45
+ ensure
46
+ fh.close if fh and block_given?
47
+ end
48
+ end
49
+
50
+ def initialize(file, mode="r")
51
+ super(file, "r+") # "r#{'+' unless mode=='r'}"
52
+ @offset = 0
53
+ while line = gets
54
+ @offset += line.size
55
+ break if line =~ /^__END__$/
56
+ end
57
+ unless line then
58
+ file_seek(-1, IO::SEEK_CUR)
59
+ unless read(1) == "\n" then
60
+ puts
61
+ @offset += 1
62
+ end
63
+ print "__END__\n"
64
+ @offset += 8
65
+ end
66
+ case mode
67
+ when /^w/: truncate
68
+ when /^a/: read
69
+ end
70
+ end
71
+
72
+ public :each, :each_byte, :each_line
73
+ public :gets, :getc, :read, :readchar, :readline, :readlines
74
+ public :puts, :putc, :print, :printf, :write
75
+ public :ctime, :atime, :mtime
76
+
77
+ alias file_seek seek unless method_defined?(:file_seek)
78
+ private :file_seek
79
+
80
+ def seek(offset=0, type=IO::SEEK_SET)
81
+ raise ArgumentError, "negative seeks currently not supported" if offset < 0
82
+ raise ArgumentError, "no type but IO::SEEK_SET supported at the moment" if type != IO::SEEK_SET
83
+ super(offset+@offset)
84
+ end
85
+
86
+ def truncate(bytes=0)
87
+ super(bytes+@offset)
88
+ seek(bytes)
89
+ 0
90
+ end
91
+
92
+ def tell
93
+ super-@offset
94
+ end
95
+
96
+ def pos
97
+ super-@offset
98
+ end
99
+
100
+ public :close
101
+ end
@@ -0,0 +1,86 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ require 'erb'
10
+ require 'ostruct'
11
+
12
+
13
+
14
+ class Templater
15
+ Raiser = proc { |e|
16
+ raise
17
+ }
18
+ Teller = proc { |e|
19
+ "<<#{e.class}: #{e}>>"
20
+ }
21
+
22
+ class Variables < OpenStruct
23
+ def initialize(delegator=nil, variables={}, &on_error)
24
+ super(variables)
25
+ @delegator = delegator
26
+ @on_error = on_error || RaiseExceptions
27
+ end
28
+
29
+ def method_missing(m, *a, &b)
30
+ if @table.key?(m) || m.to_s =~ /=$/ then
31
+ super
32
+ elsif @delegator && @delegator.respond_to?(m) then
33
+ @delegator.send(m, *a, &b) if @delegator
34
+ else
35
+ raise NameError, "undefined local variable or method `#{m}'"
36
+ end
37
+ rescue Exception => e
38
+ @on_error.call(e)
39
+ end
40
+
41
+ def inspect
42
+ @table.inspect
43
+ end
44
+ end
45
+
46
+ # Option defaults
47
+ Opt = {
48
+ :safe_level => nil,
49
+ :trim_mode => '%<>',
50
+ :eoutvar => '_erbout'
51
+ }
52
+ # binding method
53
+ Binder = Object.instance_method(:binding)
54
+
55
+ attr_reader :string
56
+ def initialize(string, opt={})
57
+ opt, string = string, nil if string.kind_of?(Hash)
58
+ opt = Opt.merge(opt)
59
+ file = nil
60
+ if !string || File.exist?(string) then
61
+ string ||= opt[:filename]
62
+ file = string
63
+ string = File.read(string)
64
+ end
65
+ @string = string.dup.freeze
66
+ @erb = ERB.new(@string, *opt.values_at(:safe_level, :trim_mode, :eoutvar))
67
+ @erb.filename = file if file
68
+ end
69
+
70
+ def result(delegator=nil, variables={}, &on_error)
71
+ variables ||= {}
72
+ on_error ||= Raiser
73
+ variables = Variables.new(delegator, variables, &on_error) unless variables.kind_of?(Variables)
74
+ @erb.result(Binder.bind(variables).call)
75
+ rescue NameError => e
76
+ raise NameError, e.message+" for #{self.inspect} with #{variables.inspect}", e.backtrace
77
+ end
78
+
79
+ def inspect # :nodoc:
80
+ "#<%s:0x%x string=%s>" % [
81
+ self.class,
82
+ object_id << 1,
83
+ @string.inspect
84
+ ]
85
+ end
86
+ end
@@ -0,0 +1,134 @@
1
+ require 'pp'
2
+ require 'test/unit'
3
+
4
+ class TestCLOptions < Test::Unit::TestCase
5
+ def setup
6
+ # if you prefer methods over bullet lists, o is just an alias to option
7
+ @options = CLOptions.new("file1 file2 [file3]") {
8
+ application_name 'app' # optional, defaults to $0
9
+ #required_options %w(-p) # optional (obviously)
10
+
11
+ o nil, '--help', "Display this help."
12
+ o '-i', '--interactive', "Don't deamonize, lets process run interactively in Terminal."
13
+ o '-p', '--port', 'PORT', "On what port to run the server."
14
+ o '-v', '--version', "Prints the version and quits."
15
+ }
16
+ end
17
+
18
+ def test_flags
19
+ flag1 = CLOptions::Switch.new('-p')
20
+ flag2 = CLOptions::Switch.new('-p', 'Help')
21
+ flag3 = CLOptions::Switch.new('-p', '--port', 'Help')
22
+ flag4 = CLOptions::Switch.new('-p', '--port', nil, 'Help')
23
+ flag5 = CLOptions::Switch.new('-p', '--port', 'INTEGER', 'Help')
24
+ flag6 = CLOptions::Switch.new('-p', '--port', 'INTEGER', true, 'Help')
25
+ flag7 = CLOptions::Switch.new('-p', '--port', 'INTEGER', :portmap, 'Help')
26
+ flag8 = CLOptions::Switch.new('-p', '--port', 'INTEGER', :portmap, 'Help', &CLOptions::Integer)
27
+
28
+ assert_equal('-p', flag1.short)
29
+ assert_equal(nil, flag1.long)
30
+ assert_equal([], flag1.params)
31
+ assert_equal(%w(-p), flag1.mappings)
32
+ assert_equal(nil, flag1.hash_key)
33
+ assert_equal('', flag1.help)
34
+ assert_equal('-p', flag1.to_s)
35
+
36
+ assert_equal('-p', flag2.short)
37
+ assert_equal(nil, flag2.long)
38
+ assert_equal([], flag2.params)
39
+ assert_equal(%w(-p), flag2.mappings)
40
+ assert_equal(nil, flag2.hash_key)
41
+ assert_equal('Help', flag2.help)
42
+ assert_equal('-p', flag2.to_s)
43
+
44
+ assert_equal('-p', flag3.short)
45
+ assert_equal('--port', flag3.long)
46
+ assert_equal([], flag3.params)
47
+ assert_equal(%w(-p --port), flag3.mappings)
48
+ assert_equal(nil, flag3.hash_key)
49
+ assert_equal('Help', flag3.help)
50
+ assert_equal('-p, --port', flag3.to_s)
51
+
52
+ assert_equal('-p', flag5.short)
53
+ assert_equal('--port', flag5.long)
54
+ assert_equal(['INTEGER'], flag5.params)
55
+ assert_equal(%w(-p --port), flag5.mappings)
56
+ assert_equal(nil, flag5.hash_key)
57
+ assert_equal('Help', flag5.help)
58
+ assert_equal('-p, --port INTEGER', flag5.to_s)
59
+
60
+ assert_equal('-p', flag6.short)
61
+ assert_equal('--port', flag6.long)
62
+ assert_equal(['INTEGER'], flag6.params)
63
+ assert_equal(['-p', '--port', :port], flag6.mappings)
64
+ assert_equal(:port, flag6.hash_key)
65
+ assert_equal('Help', flag6.help)
66
+ assert_equal('-p, --port INTEGER', flag6.to_s)
67
+
68
+ assert_equal('-p', flag7.short)
69
+ assert_equal('--port', flag7.long)
70
+ assert_equal(['INTEGER'], flag7.params)
71
+ assert_equal(['-p', '--port', :portmap], flag7.mappings)
72
+ assert_equal(:portmap, flag7.hash_key)
73
+ assert_equal('Help', flag7.help)
74
+ assert_equal('-p, --port INTEGER', flag7.to_s)
75
+
76
+ assert_equal('-p', flag8.short)
77
+ assert_equal('--port', flag8.long)
78
+ assert_equal(['INTEGER'], flag8.params)
79
+ assert_equal(['-p', '--port', :portmap], flag8.mappings)
80
+ assert_equal(:portmap, flag8.hash_key)
81
+ assert_equal('Help', flag8.help)
82
+ assert_equal('-p, --port INTEGER', flag8.to_s)
83
+
84
+ flag = flag8.process(nil, ["1234"])
85
+ assert_equal(1234, flag.parameters)
86
+ end
87
+
88
+ def test_parsing1
89
+ result = nil
90
+ assert_nothing_raised { result = @options.parse(%w(-p 1234 --interactive fubu fubar)) }
91
+
92
+ assert_equal("fubu", result.argv.file1)
93
+ assert_equal("fubu", result.argv[0])
94
+ assert_equal("fubar", result.argv.file2)
95
+ assert_equal("fubar", result.argv[1])
96
+ assert_equal(nil, result.argv.file3)
97
+
98
+ assert_equal("1234", result['-p'])
99
+ assert_equal("1234", result['--port'])
100
+ assert_equal(true, result['-i'])
101
+ assert_equal(true, result['--interactive'])
102
+ assert_equal(nil, result['-v'])
103
+ assert_equal(nil, result['--version'])
104
+ end
105
+
106
+ def test_usage
107
+ assert_equal(<<EOUSAGE, @options.usage(false))
108
+ Usage:
109
+ app -iv -p PORT --help file1 file2 [file3]
110
+ EOUSAGE
111
+ assert_equal(<<EOUSAGE, @options.usage(true))
112
+ Usage:
113
+ app -iv -p PORT --help --interactive --port PORT --version file1 file2 [file3]
114
+ EOUSAGE
115
+ end
116
+
117
+ def test_help
118
+ assert_equal(<<EOUSAGE, @options.help)
119
+ app file1 file2 [file3]
120
+
121
+ --help
122
+ Display this help.
123
+ -i, --interactive
124
+ Don't deamonize, lets process run interactively in Terminal.
125
+ -p, --port PORT
126
+ On what port to run the server.
127
+ -v, --version
128
+ Prints the version and quits.
129
+ EOUSAGE
130
+ end
131
+
132
+ def test_options
133
+ end
134
+ end