butler 1.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +4 -0
- data/GPL.txt +340 -0
- data/LICENSE.txt +52 -0
- data/README +37 -0
- data/Rakefile +334 -0
- data/bin/botcontrol +230 -0
- data/data/butler/config_template.yaml +4 -0
- data/data/butler/dialogs/backup.rb +19 -0
- data/data/butler/dialogs/botcontrol.rb +4 -0
- data/data/butler/dialogs/config.rb +1 -0
- data/data/butler/dialogs/create.rb +53 -0
- data/data/butler/dialogs/delete.rb +3 -0
- data/data/butler/dialogs/en/backup.yaml +6 -0
- data/data/butler/dialogs/en/botcontrol.yaml +5 -0
- data/data/butler/dialogs/en/create.yaml +11 -0
- data/data/butler/dialogs/en/delete.yaml +2 -0
- data/data/butler/dialogs/en/help.yaml +17 -0
- data/data/butler/dialogs/en/info.yaml +13 -0
- data/data/butler/dialogs/en/list.yaml +4 -0
- data/data/butler/dialogs/en/notyetimplemented.yaml +2 -0
- data/data/butler/dialogs/en/rename.yaml +3 -0
- data/data/butler/dialogs/en/start.yaml +3 -0
- data/data/butler/dialogs/en/sync_plugins.yaml +3 -0
- data/data/butler/dialogs/en/uninstall.yaml +5 -0
- data/data/butler/dialogs/en/unknown_command.yaml +2 -0
- data/data/butler/dialogs/help.rb +11 -0
- data/data/butler/dialogs/info.rb +27 -0
- data/data/butler/dialogs/interactive.rb +1 -0
- data/data/butler/dialogs/list.rb +10 -0
- data/data/butler/dialogs/notyetimplemented.rb +1 -0
- data/data/butler/dialogs/rename.rb +4 -0
- data/data/butler/dialogs/selectbot.rb +2 -0
- data/data/butler/dialogs/start.rb +5 -0
- data/data/butler/dialogs/sync_plugins.rb +30 -0
- data/data/butler/dialogs/uninstall.rb +17 -0
- data/data/butler/dialogs/unknown_command.rb +1 -0
- data/data/butler/plugins/core/logout.rb +41 -0
- data/data/butler/plugins/core/plugins.rb +134 -0
- data/data/butler/plugins/core/privilege.rb +103 -0
- data/data/butler/plugins/core/user.rb +166 -0
- data/data/butler/plugins/dev/eval.rb +64 -0
- data/data/butler/plugins/dev/nometa.rb +14 -0
- data/data/butler/plugins/dev/onhandlers.rb +93 -0
- data/data/butler/plugins/dev/raw.rb +36 -0
- data/data/butler/plugins/dev/rawlog.rb +77 -0
- data/data/butler/plugins/games/eightball.rb +54 -0
- data/data/butler/plugins/games/mastermind.rb +174 -0
- data/data/butler/plugins/irc/action.rb +36 -0
- data/data/butler/plugins/irc/join.rb +38 -0
- data/data/butler/plugins/irc/notice.rb +36 -0
- data/data/butler/plugins/irc/part.rb +38 -0
- data/data/butler/plugins/irc/privmsg.rb +36 -0
- data/data/butler/plugins/irc/quit.rb +36 -0
- data/data/butler/plugins/operator/deop.rb +41 -0
- data/data/butler/plugins/operator/devoice.rb +41 -0
- data/data/butler/plugins/operator/limit.rb +47 -0
- data/data/butler/plugins/operator/op.rb +41 -0
- data/data/butler/plugins/operator/voice.rb +41 -0
- data/data/butler/plugins/public/help.rb +69 -0
- data/data/butler/plugins/public/login.rb +72 -0
- data/data/butler/plugins/public/usage.rb +49 -0
- data/data/butler/plugins/service/clones.rb +56 -0
- data/data/butler/plugins/service/define.rb +47 -0
- data/data/butler/plugins/service/log.rb +183 -0
- data/data/butler/plugins/service/svn.rb +91 -0
- data/data/butler/plugins/util/cycle.rb +98 -0
- data/data/butler/plugins/util/load.rb +41 -0
- data/data/butler/plugins/util/pong.rb +29 -0
- data/data/butler/strings/random/acknowledge.en.yaml +5 -0
- data/data/butler/strings/random/gratitude.en.yaml +3 -0
- data/data/butler/strings/random/hello.en.yaml +4 -0
- data/data/butler/strings/random/ignorance.en.yaml +7 -0
- data/data/butler/strings/random/ignorance_about.en.yaml +3 -0
- data/data/butler/strings/random/insult.en.yaml +3 -0
- data/data/butler/strings/random/rejection.en.yaml +12 -0
- data/data/man/botcontrol.1 +17 -0
- data/lib/access.rb +187 -0
- data/lib/access/admin.rb +16 -0
- data/lib/access/privilege.rb +122 -0
- data/lib/access/role.rb +102 -0
- data/lib/access/savable.rb +18 -0
- data/lib/access/user.rb +180 -0
- data/lib/access/yamlbase.rb +126 -0
- data/lib/butler.rb +188 -0
- data/lib/butler/bot.rb +247 -0
- data/lib/butler/control.rb +93 -0
- data/lib/butler/dialog.rb +64 -0
- data/lib/butler/initialvalues.rb +40 -0
- data/lib/butler/irc/channel.rb +135 -0
- data/lib/butler/irc/channels.rb +96 -0
- data/lib/butler/irc/client.rb +351 -0
- data/lib/butler/irc/hostmask.rb +53 -0
- data/lib/butler/irc/message.rb +184 -0
- data/lib/butler/irc/parser.rb +125 -0
- data/lib/butler/irc/parser/commands.rb +83 -0
- data/lib/butler/irc/parser/generic.rb +343 -0
- data/lib/butler/irc/socket.rb +378 -0
- data/lib/butler/irc/string.rb +186 -0
- data/lib/butler/irc/topic.rb +15 -0
- data/lib/butler/irc/user.rb +265 -0
- data/lib/butler/irc/users.rb +112 -0
- data/lib/butler/plugin.rb +249 -0
- data/lib/butler/plugin/configproxy.rb +35 -0
- data/lib/butler/plugin/mapper.rb +85 -0
- data/lib/butler/plugin/matcher.rb +55 -0
- data/lib/butler/plugin/onhandlers.rb +70 -0
- data/lib/butler/plugin/trigger.rb +58 -0
- data/lib/butler/plugins.rb +147 -0
- data/lib/butler/version.rb +17 -0
- data/lib/cloptions.rb +217 -0
- data/lib/cloptions/adapters.rb +24 -0
- data/lib/cloptions/switch.rb +132 -0
- data/lib/configuration.rb +223 -0
- data/lib/dialogline.rb +296 -0
- data/lib/dialogline/localizations.rb +24 -0
- data/lib/durations.rb +57 -0
- data/lib/event.rb +295 -0
- data/lib/event/at.rb +64 -0
- data/lib/event/every.rb +56 -0
- data/lib/event/timed.rb +112 -0
- data/lib/installer.rb +75 -0
- data/lib/iterator.rb +34 -0
- data/lib/log.rb +68 -0
- data/lib/log/comfort.rb +85 -0
- data/lib/log/converter.rb +23 -0
- data/lib/log/entry.rb +152 -0
- data/lib/log/fakeio.rb +55 -0
- data/lib/log/file.rb +54 -0
- data/lib/log/filereader.rb +81 -0
- data/lib/log/forward.rb +49 -0
- data/lib/log/methods.rb +39 -0
- data/lib/log/nolog.rb +18 -0
- data/lib/log/splitter.rb +26 -0
- data/lib/ostructfixed.rb +26 -0
- data/lib/ruby/array/columnize.rb +38 -0
- data/lib/ruby/dir/mktree.rb +28 -0
- data/lib/ruby/enumerable/join.rb +13 -0
- data/lib/ruby/exception/detailed.rb +24 -0
- data/lib/ruby/file/append.rb +11 -0
- data/lib/ruby/file/write.rb +11 -0
- data/lib/ruby/hash/zip.rb +15 -0
- data/lib/ruby/kernel/bench.rb +15 -0
- data/lib/ruby/kernel/daemonize.rb +42 -0
- data/lib/ruby/kernel/non_verbose.rb +17 -0
- data/lib/ruby/kernel/safe_fork.rb +18 -0
- data/lib/ruby/range/stepped.rb +11 -0
- data/lib/ruby/string/arguments.rb +72 -0
- data/lib/ruby/string/chunks.rb +15 -0
- data/lib/ruby/string/post_arguments.rb +44 -0
- data/lib/ruby/string/unescaped.rb +17 -0
- data/lib/scheduler.rb +164 -0
- data/lib/scriptfile.rb +101 -0
- data/lib/templater.rb +86 -0
- data/test/cloptions.rb +134 -0
- data/test/cv.rb +28 -0
- data/test/irc/client.rb +85 -0
- data/test/irc/client_login.txt +53 -0
- data/test/irc/client_subscribe.txt +8 -0
- data/test/irc/message.rb +30 -0
- data/test/irc/messages.txt +64 -0
- data/test/irc/parser.rb +13 -0
- data/test/irc/profile_parser.rb +12 -0
- data/test/irc/users.rb +28 -0
- metadata +256 -0
data/lib/log/nolog.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Log
|
10
|
+
# discards all messages
|
11
|
+
class NoLog
|
12
|
+
def respond_to?(m,*a)
|
13
|
+
true
|
14
|
+
end
|
15
|
+
def method_missing(*a)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/lib/log/splitter.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
module Log
|
2
|
+
class Splitter
|
3
|
+
def initialize(*receivers)
|
4
|
+
@receivers = receivers
|
5
|
+
end
|
6
|
+
|
7
|
+
def delete(receiver)
|
8
|
+
@receivers.delete(receiver)
|
9
|
+
end
|
10
|
+
|
11
|
+
def add(receiver)
|
12
|
+
@receivers << receiver
|
13
|
+
end
|
14
|
+
|
15
|
+
def method_missing(*a, &b)
|
16
|
+
@receivers.each { |r| r.__send__(*a, &b)
|
17
|
+
end
|
18
|
+
|
19
|
+
def inspect
|
20
|
+
"#<%s:%08x %s %s>" % [
|
21
|
+
self.class,
|
22
|
+
object_id,
|
23
|
+
@receivers.map { |r| r.inspect }.join(', ')
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
data/lib/ostructfixed.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
require 'ostruct'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
class OpenStruct
|
14
|
+
def [](field)
|
15
|
+
@table[field.to_sym]
|
16
|
+
end
|
17
|
+
|
18
|
+
def []=(field,value)
|
19
|
+
new_ostruct_member(field)
|
20
|
+
@table[field.to_sym] = value
|
21
|
+
end
|
22
|
+
|
23
|
+
def to_hash
|
24
|
+
@table.dup
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class Array
|
10
|
+
ColumnizeDefaults = {
|
11
|
+
:prepend => "",
|
12
|
+
:orientation => :vertical,
|
13
|
+
:spacing => 1
|
14
|
+
}
|
15
|
+
|
16
|
+
def columnize(columns=nil, opts={})
|
17
|
+
pre, ori, space = ColumnizeDefaults.merge(opts).values_at(:prepend, :orientation, :spacing)
|
18
|
+
columns ||= 2
|
19
|
+
numrows = length.quo(columns).ceil
|
20
|
+
sizes, print = Array.new(columns) { [] }, Array.new(numrows) { [] }
|
21
|
+
|
22
|
+
if ori == :vertical then
|
23
|
+
(self+Array.new(numrows*columns-length,"")).each_with_index { |e,i|
|
24
|
+
sizes[i.div(numrows)] << e
|
25
|
+
print[i%numrows] << e
|
26
|
+
}
|
27
|
+
else
|
28
|
+
(self+Array.new(numrows*columns-length,"")).each_with_index { |e,i|
|
29
|
+
sizes[i%columns] << e
|
30
|
+
print[i.div(columns)] << e
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
sizes = sizes.map { |e| e.map { |f| f.length }.max+space }
|
35
|
+
format = "#{pre}%-#{sizes.join('s %-')}s"
|
36
|
+
print.map { |e| format % e }.join("\n")
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class <<Dir
|
10
|
+
# create directory structure
|
11
|
+
# Dir.mktree(
|
12
|
+
# "a" => {
|
13
|
+
# "b" => [
|
14
|
+
# "d",
|
15
|
+
# "e"
|
16
|
+
# ],
|
17
|
+
# },
|
18
|
+
# "in/directory"
|
19
|
+
# )
|
20
|
+
def mktree(tree, base=Dir.pwd)
|
21
|
+
dir = [];
|
22
|
+
tree.each { |dir, sub|
|
23
|
+
current = "#{base}/#{dir}"
|
24
|
+
mkdir(current)
|
25
|
+
mktree(sub, current) if sub
|
26
|
+
}
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
class Exception
|
2
|
+
module Detailed
|
3
|
+
def self.extended(obj)
|
4
|
+
obj.initialize_details
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize_details
|
8
|
+
@prepend = []
|
9
|
+
@append = []
|
10
|
+
end
|
11
|
+
|
12
|
+
def prepend(string)
|
13
|
+
@prepend.unshift string
|
14
|
+
end
|
15
|
+
|
16
|
+
def append(string)
|
17
|
+
@append.unshift string
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
(@prepend+[super]+@append).join(' ')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
# create a hash from an array with keys and an array with values
|
10
|
+
# you can set default or provide a block just as with Hash::new
|
11
|
+
def Hash.zip(keys, values, default=nil, &block)
|
12
|
+
hash = block_given? ? Hash.new(&block) : Hash.new(default)
|
13
|
+
keys.zip(values) { |k,v| hash[k]=v }
|
14
|
+
hash
|
15
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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/safe_fork'
|
10
|
+
|
11
|
+
|
12
|
+
|
13
|
+
|
14
|
+
module Kernel
|
15
|
+
# This method causes the current running process to become a daemon
|
16
|
+
# All further printing is relied to the error.log
|
17
|
+
# FIXME doesn't belong into Butler::Bot, rather into botcontrol
|
18
|
+
def daemonize(chdir=nil, &on_sighup)
|
19
|
+
srand # Split rand streams between spawning and daemonized process
|
20
|
+
safe_fork and exit # Fork and exit from the parent
|
21
|
+
|
22
|
+
# Detach from the controlling terminal
|
23
|
+
raise "Can't detach from controlling terminal" unless sess_id = Process.setsid
|
24
|
+
|
25
|
+
# Prevent the possibility of acquiring a controlling terminal
|
26
|
+
trap('SIGHUP', 'IGNORE')
|
27
|
+
exit if safe_fork
|
28
|
+
|
29
|
+
# In daemon mode, a SIGHUP means termination
|
30
|
+
trap('SIGHUP', &on_sighup)
|
31
|
+
|
32
|
+
# We can't get the originally controlling terminals stdout/stdin anymore
|
33
|
+
STDIN.reopen("/dev/null")
|
34
|
+
STDOUT.reopen("/dev/null", "a")
|
35
|
+
STDERR.reopen(STDOUT)
|
36
|
+
|
37
|
+
Dir.chdir(chdir) if chdir
|
38
|
+
File.umask 0033 # FIXME ask somebody knowledgable about a sensible value
|
39
|
+
|
40
|
+
sess_id
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Kernel
|
10
|
+
def non_verbose
|
11
|
+
old_verbose = $VERBOSE
|
12
|
+
$VERBOSE = false
|
13
|
+
yield
|
14
|
+
ensure
|
15
|
+
$VERBOSE = old_verbose
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
module Kernel
|
10
|
+
# Try to fork if at all possible retrying every +delay+ sec (5s default)
|
11
|
+
# if the maximum process limit for the system has been reached
|
12
|
+
def safe_fork(delay=5)
|
13
|
+
fork
|
14
|
+
rescue Errno::EWOULDBLOCK
|
15
|
+
sleep(delay)
|
16
|
+
retry
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
require 'ruby/string/unescaped'
|
10
|
+
|
11
|
+
class String
|
12
|
+
# the exception raised by String#arguments if an odd number of arguments is encountered.
|
13
|
+
# you can still extract the other parts of the parsing via its accessors.
|
14
|
+
class SingleQuoteException < RuntimeError
|
15
|
+
attr_reader :index
|
16
|
+
attr_reader :pre
|
17
|
+
attr_reader :post
|
18
|
+
def initialize(args, index)
|
19
|
+
@index, @pre, @post = index, args[0,index], args[index+1,args.length-index]
|
20
|
+
super("A single unescaped quote as argument #{index}")
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
# parse a string of single/double/unquoted arguments (or any mix of)
|
25
|
+
# raises an exception if an odd number of quotes is matched
|
26
|
+
# examples:
|
27
|
+
# 'hello hello "ruby world"'.arguments # => ["hello", "hello", "ruby world"]
|
28
|
+
# 'hello hello ruby\ world'.arguments # => ["hello", "hello", "ruby world"]
|
29
|
+
# 'hello hello ruby\ world'.arguments(false) # => ["hello", "hello", "ruby\\ world"]
|
30
|
+
def arguments(unescape=true)
|
31
|
+
args = scan(
|
32
|
+
/
|
33
|
+
# match a double quoted string
|
34
|
+
"(?:\\.|[^\\"])*" |
|
35
|
+
|
36
|
+
# match a single quoted string
|
37
|
+
'(?:\\.|[^\\'])*' |
|
38
|
+
|
39
|
+
# match non-quoted words (may contain escaped spaces)
|
40
|
+
(?:\\.|[^\\'"\s])+ |
|
41
|
+
|
42
|
+
# match a single " or '
|
43
|
+
["']
|
44
|
+
/x
|
45
|
+
)
|
46
|
+
if unescape
|
47
|
+
args.map! { |arg| ((arg[0,1] == '"' && arg[1]) ? arg[1..-2] : arg).unescaped }
|
48
|
+
else
|
49
|
+
args.map! { |arg| ((arg[0,1] == '"' && arg[1]) ? arg[1..-2] : arg) }
|
50
|
+
end
|
51
|
+
if (sq = args.index('"')) || (sq = args.index("'")) then
|
52
|
+
raise SingleQuoteException.new(args, sq)
|
53
|
+
end
|
54
|
+
args
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
if __FILE__ == $0 then
|
59
|
+
require 'test/unit'
|
60
|
+
class TestStringArguments < Test::Unit::TestCase
|
61
|
+
def test_all
|
62
|
+
assert_equal(%w(), ''.arguments)
|
63
|
+
assert_equal(%w(hello world those are arguments), 'hello world those are arguments'.arguments)
|
64
|
+
assert_equal(%w(hello ruby\ world those are arguments), 'hello "ruby world" those are arguments'.arguments)
|
65
|
+
assert_equal(%w(hello ruby\ world), 'hello "ruby world"'.arguments)
|
66
|
+
assert_equal(%w(ruby\ world those are arguments), '"ruby world" those are arguments'.arguments)
|
67
|
+
assert_equal(%w(hello ruby\ world those are arguments), 'hello ruby\ world those are arguments'.arguments)
|
68
|
+
assert_raise(String::SingleQuoteException) { 'hello " ruby'.arguments }
|
69
|
+
assert_raise(String::SingleQuoteException) { "hello ' ruby".arguments }
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
class String
|
10
|
+
# splits a string into chunks of length 'len'
|
11
|
+
def chunks(chunk_length)
|
12
|
+
scan(/.{1,#{chunk_length}}/)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
#--
|
2
|
+
# Copyright 2007 by Stefan Rusterholz.
|
3
|
+
# All rights reserved.
|
4
|
+
# See LICENSE.txt for permissions.
|
5
|
+
#++
|
6
|
+
|
7
|
+
|
8
|
+
|
9
|
+
require 'ruby/string/arguments'
|
10
|
+
|
11
|
+
class String
|
12
|
+
def post_arguments(unescaped=true)
|
13
|
+
post = []
|
14
|
+
offset = -1
|
15
|
+
found = 0
|
16
|
+
arguments = begin
|
17
|
+
arguments(false)
|
18
|
+
rescue SingleQuoteException => ex
|
19
|
+
ex.pre+[ex.post.join(" ")]
|
20
|
+
end
|
21
|
+
arguments.each { |argument|
|
22
|
+
post << (unescaped ? self[offset+1..-1].unescaped : self[offset+1..-1])
|
23
|
+
found = index(argument, offset+1)
|
24
|
+
offset = found+argument.length
|
25
|
+
}
|
26
|
+
post
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
if __FILE__ == $0 then
|
31
|
+
require 'test/unit'
|
32
|
+
class TestStringArguments < Test::Unit::TestCase
|
33
|
+
def test_all
|
34
|
+
#assert_equal(%w(), ''.arguments)
|
35
|
+
#assert_equal(%w(hello world those are arguments), 'hello world those are arguments'.arguments)
|
36
|
+
#assert_equal(%w(hello ruby\ world those are arguments), 'hello "ruby world" those are arguments'.arguments)
|
37
|
+
#assert_equal(%w(hello ruby\ world), 'hello "ruby world"'.arguments)
|
38
|
+
#assert_equal(%w(ruby\ world those are arguments), '"ruby world" those are arguments'.arguments)
|
39
|
+
#assert_equal(%w(hello ruby\ world those are arguments), 'hello ruby\ world those are arguments'.arguments)
|
40
|
+
#assert_raise(String::SingleQuoteException) { 'hello " ruby'.arguments }
|
41
|
+
#assert_raise(String::SingleQuoteException) { "hello ' ruby".arguments }
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|