gnn-rblibs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 tarao
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,32 @@
1
+ = gnn-rblibs
2
+
3
+ Some Ruby tweaks.
4
+
5
+ == Installation
6
+
7
+ First, make your gem source gemcutter by
8
+
9
+ gem install gemcutter
10
+ gem tumble
11
+
12
+ or
13
+
14
+ gem sources -a http://gemcutter.org
15
+
16
+ then
17
+
18
+ gem install gnn-rblibs
19
+
20
+ == Note on Patches/Pull Requests
21
+
22
+ * Fork the project.
23
+ * Make your feature addition or bug fix.
24
+ * Add tests for it. This is important so I don't break it in a
25
+ future version unintentionally.
26
+ * Commit, do not mess with rakefile, version, or history.
27
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
28
+ * Send me a pull request. Bonus points for topic branches.
29
+
30
+ == Copyright
31
+
32
+ Copyright (c) 2009 tarao. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "gnn-rblibs"
8
+ gem.summary = %Q{Some Ruby tweaks}
9
+ gem.description = %Q{Some Ruby tweaks for file operations, commandline parsers, etc.}
10
+ gem.email = "tarao.gnn@gmail.com"
11
+ gem.homepage = "http://github.com/tarao/gnn-rblibs"
12
+ gem.authors = ["tarao"]
13
+ gem.add_development_dependency "rspec", ">= 1.2.9"
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'spec/rake/spectask'
22
+ Spec::Rake::SpecTask.new(:spec) do |spec|
23
+ spec.libs << 'lib' << 'spec'
24
+ spec.spec_files = FileList['spec/**/*_spec.rb']
25
+ end
26
+
27
+ Spec::Rake::SpecTask.new(:rcov) do |spec|
28
+ spec.libs << 'lib' << 'spec'
29
+ spec.pattern = 'spec/**/*_spec.rb'
30
+ spec.rcov = true
31
+ end
32
+
33
+ task :spec => :check_dependencies
34
+
35
+ task :default => :spec
36
+
37
+ require 'rake/rdoctask'
38
+ Rake::RDocTask.new do |rdoc|
39
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
40
+
41
+ rdoc.rdoc_dir = 'rdoc'
42
+ rdoc.title = "gnn-rblibs #{version}"
43
+ rdoc.rdoc_files.include('README*')
44
+ rdoc.rdoc_files.include('lib/**/*.rb')
45
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,67 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{gnn-rblibs}
8
+ s.version = "0.0.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["tarao"]
12
+ s.date = %q{2009-11-28}
13
+ s.description = %q{Some Ruby tweaks for file operations, commandline parsers, etc.}
14
+ s.email = %q{tarao.gnn@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "gnn-rblibs.gemspec",
27
+ "lib/dir/each_leaf.rb",
28
+ "lib/file/kind.rb",
29
+ "lib/file/observer.rb",
30
+ "lib/fileutils/sync.rb",
31
+ "lib/getopt.rb",
32
+ "lib/loadconf.rb",
33
+ "lib/plugin.rb",
34
+ "lib/process/invoke.rb",
35
+ "lib/rbconfig/command.rb",
36
+ "lib/string/random.rb",
37
+ "lib/term/countdown.rb",
38
+ "lib/webrick/single_thread_server.rb",
39
+ "lib/www/mechanize/get.rb",
40
+ "spec/gnn-rblibs_spec.rb",
41
+ "spec/spec.opts",
42
+ "spec/spec_helper.rb"
43
+ ]
44
+ s.homepage = %q{http://github.com/tarao/gnn-rblibs}
45
+ s.rdoc_options = ["--charset=UTF-8"]
46
+ s.require_paths = ["lib"]
47
+ s.rubygems_version = %q{1.3.5}
48
+ s.summary = %q{Some Ruby tweaks}
49
+ s.test_files = [
50
+ "spec/spec_helper.rb",
51
+ "spec/gnn-rblibs_spec.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
+ s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
60
+ else
61
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
62
+ end
63
+ else
64
+ s.add_dependency(%q<rspec>, [">= 1.2.9"])
65
+ end
66
+ end
67
+
@@ -0,0 +1,17 @@
1
+ class Dir
2
+ def self.children(path, flag=0)
3
+ c = self.glob(File.join(path, '*'), flag).reject{|f| f=~/\/\.+$/}
4
+ return block_given? ? c.each(&Proc.new) : c
5
+ end
6
+
7
+ def self.each_leaf(path, flag=0, nofollow=false, block=nil)
8
+ block = Proc.new if block_given?
9
+ if (!nofollow || !File.symlink?(path)) && File.directory?(path)
10
+ self.children(path, flag) do |child|
11
+ self.each_leaf(child, flag, nofollow, block) # recursive
12
+ end
13
+ else
14
+ block && block.call(path)
15
+ end
16
+ end
17
+ end
data/lib/file/kind.rb ADDED
@@ -0,0 +1,8 @@
1
+ class File
2
+ def self.kind(file, nofollow=false)
3
+ k = [ :directory, :file ]
4
+ k.unshift(:symlink) if nofollow
5
+ return k.find{|w| self.send(w.to_s+'?', file)}
6
+ end
7
+ end
8
+
@@ -0,0 +1,138 @@
1
+ class File
2
+ class Observer
3
+ ACCESS = 0x0001
4
+ MODIFY = 0x0002
5
+ ATTRIB = 0x0004
6
+ # CLOSE_WRITE = 0x0008
7
+ # CLOSE_NOWRITE = 0x0010
8
+ # OPEN = 0x0020
9
+ MOVED_FROM = 0x0040
10
+ MOVED_TO = 0x0080
11
+ CREATE = 0x0100
12
+ DELETE = 0x0200
13
+ # DELETE_SELF = 0x0400
14
+ # MOVE_SELF = 0x0800
15
+ # CLOSE = CLOSE_WRITE | CLOSE_NOWRITE
16
+ MOVE = MOVED_FROM | MOVED_TO
17
+ CHANGE = MODIFY | ATTRIB | MOVE | CREATE | DELETE
18
+
19
+ class Win32
20
+ def self.installed?
21
+ begin
22
+ require 'rubygems'
23
+ require 'win32/changenotify'
24
+ rescue LoadError
25
+ return false
26
+ end
27
+ return self
28
+ end
29
+
30
+ def self.watch(files, events, dir = false)
31
+ mask = 0
32
+ # FIXME: more events
33
+ # mask |= ::Win32::ChangeNotify::ATTRIBUTES if (events & ATTRIB) != 0
34
+ mask |= ::Win32::ChangeNotify::DIR_NAME if (events & MOVE) != 0
35
+ mask |= ::Win32::ChangeNotify::FILE_NAME if (events & MOVE) != 0
36
+ mask |= ::Win32::ChangeNotify::LAST_WRITE if (events & CHANGE) != 0
37
+ mask |= ::Win32::ChangeNotify::SIZE if (events & CHANGE) != 0
38
+ directory = dir ? files : File.dirname(files.first)
39
+ cn = ::Win32::ChangeNotify.new(directory, false, mask)
40
+ loop do
41
+ cn.wait do |arr|
42
+ arr.each do |st|
43
+ if dir || files.find{|f| f == st.file_name}
44
+ # FIXME: convert st.action to event
45
+ yield({ :name => st.file_name,
46
+ :event => events,
47
+ :class => self })
48
+ return true
49
+ end
50
+ end
51
+ end
52
+ end
53
+ return false
54
+ end
55
+
56
+ def self.watch_dir(dir, events, &block)
57
+ return self.watch(dir, events, true, &block)
58
+ end
59
+ end
60
+
61
+ class Inotify
62
+ def self.installed?
63
+ begin
64
+ require 'inotify'
65
+ rescue LoadError
66
+ return false
67
+ end
68
+ return self
69
+ end
70
+
71
+ def self.watch(files, events)
72
+ notifier = ::Inotify.new
73
+ begin
74
+ files.each{|f| notifier.add_watch(f, events)}
75
+ notifier.each_event do |e|
76
+ yield({ :event => e.mask,
77
+ :class => self })
78
+ return true
79
+ end
80
+ ensure
81
+ notifier.close
82
+ end
83
+ return false
84
+ end
85
+
86
+ def self.watch_dir(dir, events, &block)
87
+ return self.watch(dir, events, &block)
88
+ end
89
+ end
90
+
91
+ class Naive
92
+ def self.installed?
93
+ return Naive
94
+ end
95
+
96
+ def self.watch(files, events, s=0.1)
97
+ mtime = {}
98
+ files.each{|f| mtime[f] = File.mtime(f)}
99
+
100
+ loop do
101
+ # FIXME: other events
102
+ fname = files.find{|f| File.mtime(f) != mtime[f]}
103
+ if fname
104
+ yield({ :name => fname,
105
+ :event => events,
106
+ :class => self })
107
+ return true
108
+ end
109
+ sleep(s)
110
+ end
111
+ return false
112
+ end
113
+
114
+ def self.watch_dir(dir, events, s=0.1, &block)
115
+ return self.watch(dir, events, s, &block)
116
+ end
117
+ end
118
+
119
+ def self.watch(files, events, &block)
120
+ klass = Win32.installed? || Inotify.installed? || Naive.installed?
121
+ raise 'No file observer' unless klass
122
+ files = [files] unless files.is_a?(Array)
123
+ mtime = {}
124
+ files.each{|f| mtime[f] = File.mtime(f)}
125
+ return klass.watch(files, events) do |x|
126
+ # FIXME: other events
127
+ x[:name] = x[:name] || files.find{|f| File.mtime(f) != mtime[f]}
128
+ block.call(x)
129
+ end
130
+ end
131
+
132
+ def self.watch_dir(dir, events, &block)
133
+ klass = Win32.installed? || Inotify.installed? || Naive.installed?
134
+ raise 'No file observer' unless klass
135
+ return klass.watch_dir(dir, events, &block)
136
+ end
137
+ end
138
+ end
@@ -0,0 +1,61 @@
1
+ require 'file/kind'
2
+ require 'dir/each_leaf'
3
+ require 'fileutils'
4
+
5
+ module FileUtils
6
+ class Sync
7
+ def self.each_leaf(src, dst, flag=0, nf=false, block=nil)
8
+ block = Proc.new if block_given?
9
+ if [File.kind(src, nf), File.kind(dst, nf)].all?{|k| k == :directory}
10
+ Dir.children(src, flag) do |file|
11
+ target = File.join(dst, File.basename(file))
12
+ self.each_leaf(file, target, flag, nf, block) # recursive
13
+ end
14
+ else
15
+ block && block.call(src, dst)
16
+ end
17
+ end
18
+
19
+ def self.conflict?(src, dst, nofollow=false)
20
+ return false unless File.exist?(dst)
21
+ return File.kind(src, nofollow) != File.kind(dst, nofollow)
22
+ end
23
+
24
+ def self.uptodate?(s, d)
25
+ cond = false
26
+ cond ||= !File.exist?(d)
27
+ cond ||= File.file?(s) && File.file?(d) && FileUtils.uptodate?(s, d)
28
+ return cond
29
+ end
30
+
31
+ def initialize(opt={})
32
+ @cond = opt[:cond] || {}
33
+ @cond[:conflict] ||= proc{|s,d| self.class.conflict?(s,d)}
34
+ @cond[:uptodate] ||= proc{|s,d| self.class.uptodate?(s,d)}
35
+
36
+ @method = opt[:method] || {}
37
+ @method[:conflict] ||= proc{}
38
+ @method[:uptodate] ||= proc do |s, d|
39
+ FileUtils.cp_r(s, d, {:preserve => true})
40
+ end
41
+ @method[:nothing] ||= proc{}
42
+
43
+ @flag = opt[:flag] || 0
44
+ @nofollow = opt[:nofollow] || false
45
+ end
46
+
47
+ def sync(src, dst)
48
+ self.class.each_leaf(src, dst, @flag, @nofollow) do |s,d|
49
+ none = proc{ :nothing }
50
+ what = [ :conflict, :uptodate ].find(none){|w| @cond[w].call(s, d)}
51
+ @method[what].call(s, d)
52
+ end
53
+ end
54
+ end
55
+
56
+ def sync(src, dst, opt={})
57
+ Sync.new(opt).sync(src, dst)
58
+ end
59
+
60
+ module_function :sync
61
+ end
data/lib/getopt.rb ADDED
@@ -0,0 +1,185 @@
1
+ class GetOpt
2
+ def self.escape(str, quote=true)
3
+ str = str.to_s
4
+ return str unless str.match(/[\\\"\'\s]/)
5
+ str = str.gsub(/\\/, '\\\\').gsub(/\"/, '\\\"')
6
+ return quote ? '"'+str+'"' : str
7
+ end
8
+
9
+ attr_accessor :args, :parsed, :rest, :parser
10
+
11
+ def initialize(args, *opts)
12
+ @parsed = {}
13
+ @args = []
14
+ @rest = []
15
+
16
+ # argument syntax definitions
17
+ syntax(opts[0] || [], opts[1] || {})
18
+
19
+ # custom parser
20
+ @parser = {
21
+ :custom => (opts[1].is_a?(Proc) && opts[1]) || proc{|v| eat(v)}
22
+ }
23
+
24
+ pparse_rest = proc{|n,v,a,r| parse_rest(n,v,a,r)}
25
+ pparse_val = proc{|n,v,a,r| parse_val(n,v,a,r)}
26
+ pparse_bool_short = proc{|n,v,a,r| parse_bool_short(n,v,a,r)}
27
+ pparse_bool_long = proc{|n,v,a,r| parse_bool_long(n,v,a,r)}
28
+
29
+ # parser for short arguments
30
+ @parser[:short] = {
31
+ 'b' => pparse_bool_short,
32
+ 'i' => pparse_val,
33
+ 'f' => pparse_val,
34
+ 's' => pparse_val,
35
+ }
36
+
37
+ # parser for long arguments
38
+ @parser[:long] = {
39
+ 'b' => pparse_bool_long,
40
+ 'i' => pparse_val,
41
+ 'f' => pparse_val,
42
+ 's' => pparse_val,
43
+ '' => pparse_rest, # '... -- ...' is a separator
44
+ }
45
+
46
+ return parse(args || [])
47
+ end
48
+
49
+ def syntax(opts, default={})
50
+ @full = {}
51
+ @type = {}
52
+ @default = {}
53
+ default.each{|k,v| @default[k.to_s] = v}
54
+ opts.each do |opt|
55
+ default_value = nil
56
+ if opt.is_a?(Array)
57
+ default_value = opt[1]
58
+ opt = opt[0]
59
+ end
60
+ if opt =~ /^(?:([^-=])\|)?([^-=]+)(?:=(.+))?$/
61
+ @type[$2] = $3 || 'b'
62
+ @full[$1] = $2 if $1
63
+ @default[$2.to_s] = default_value if default_value
64
+ end
65
+ end
66
+ @type[''] = ''
67
+ return self
68
+ end
69
+
70
+ def parse(args)
71
+ args = @parser[:custom].call(args) while args.length != 0
72
+ return self
73
+ end
74
+
75
+ def [](opt)
76
+ opt = opt.to_s
77
+ val = @parsed[opt]
78
+ return val == nil ? @default[opt] : val
79
+ end
80
+
81
+ def []=(opt,val)
82
+ return @parsed[opt.to_s] = val
83
+ end
84
+
85
+ def push(name, val)
86
+ if @type[name] == 'b'
87
+ if !val
88
+ @parsed[name] = false
89
+ elsif !@parsed[name]
90
+ @parsed[name] = true
91
+ elsif @parsed[name].is_a?(Integer)
92
+ @parsed[name] = @parsed[name].succ
93
+ else # @parsed[name] == true
94
+ @parsed[name] = 2 # promote to be an Integer
95
+ end
96
+ else
97
+ if @parsed[name].instance_of?(Array)
98
+ @parsed[name] << val
99
+ elsif @parsed[name]
100
+ @parsed[name] = [ @parsed[name], val ] # promote to be an Array
101
+ else
102
+ @parsed[name] = val
103
+ end
104
+ end
105
+ return self
106
+ end
107
+
108
+ def to_s
109
+ arr1 = []
110
+ @parsed.each{|name,value|
111
+ if value.is_a?(TrueClass) || value.is_a?(FalseClass)
112
+ arr1 << ('--' + (value ? '' : 'no-') + name)
113
+ elsif @type[name] == 'b' && value.is_a?(Integer)
114
+ arr1 += (1..value).map{|v| '--' + name}
115
+ elsif value.is_a?(Array)
116
+ value.each{|v| arr1 << ('--' + name + '=' + self.class.escape(v))}
117
+ else
118
+ arr1 << ('--' + name + '=' + self.class.escape(value))
119
+ end
120
+ }
121
+ arr2 = @args
122
+ arr2 += ['--'] + @rest if @rest.length > 0
123
+ return (arr1 + arr2.map{|val| self.class.escape(val)}).join(' ')
124
+ end
125
+
126
+ # predefined parsers
127
+
128
+ def parse_bool_short(name, val, arg, rest)
129
+ flags = arg[1..-1] # skip '-'
130
+ flags.each_byte do |f| # for each flag
131
+ name = @full[f.chr]
132
+ if name && @type[name] == 'b'
133
+ push(name, true)
134
+ else
135
+ parse_unknown(name, nil, '-'+f.chr, rest)
136
+ end
137
+ end
138
+ return rest
139
+ end
140
+
141
+ def parse_bool_long(name, val, arg, rest)
142
+ push(name, !( (val == 'false') ^ (arg =~ /^--no/) ))
143
+ return rest
144
+ end
145
+
146
+ def parse_val(name, val, arg, rest)
147
+ val = (val || rest.shift).send('to_' + @type[name]) # to_i, to_f, etc.
148
+ push(name, val)
149
+ return rest
150
+ end
151
+
152
+ def parse_rest(name, val, arg, rest)
153
+ @rest = rest
154
+ return []
155
+ end
156
+
157
+ def parse_unknown(name, val, arg, rest)
158
+ @args << arg
159
+ return rest
160
+ end
161
+
162
+ private
163
+
164
+ def get_parser(name, long)
165
+ parser = @parser[ long ? :long : :short ]
166
+ return parser[@type[name]] || proc{|n,v,a,r| parse_unknown(n,v,a,r)}
167
+ end
168
+
169
+ def eat(args)
170
+ arg = args.shift
171
+
172
+ long = false
173
+ name = nil
174
+ if arg =~ /^--(no-?)?([^=]*)(?:=(.*))?$/
175
+ long = true
176
+ name = (@type[$2] || !$1) ? $2 : $1+$2
177
+ val = $3
178
+ elsif arg =~ /^-([^-])(.+)?$/
179
+ name = @full[$1]
180
+ val = $2
181
+ end
182
+
183
+ return get_parser(name, long).call(name, val, arg, args)
184
+ end
185
+ end
data/lib/loadconf.rb ADDED
@@ -0,0 +1,26 @@
1
+ module LoadConf
2
+ def report(method, e)
3
+ if method.instance_of?(String)
4
+ warn(method)
5
+ elsif method.instance_of?(Proc)
6
+ method.call(e)
7
+ end
8
+ end
9
+
10
+ def load(fname, *opt)
11
+ er = opt[0] || {}
12
+ begin
13
+ open(fname) do |src|
14
+ begin
15
+ return instance_eval(src.read.untaint, fname, 1)
16
+ rescue => e
17
+ report(er[:script], e)
18
+ end
19
+ end
20
+ rescue SystemCallError => e
21
+ report(er[:open], e)
22
+ end
23
+ end
24
+
25
+ module_function :load, :report
26
+ end
data/lib/plugin.rb ADDED
@@ -0,0 +1,28 @@
1
+ class Plugin
2
+ @@list = []
3
+ def self.load(dir)
4
+ Dir::glob("#{dir}/*.rb").each do |fname|
5
+ open(fname) do |src|
6
+ begin
7
+ val = instance_eval(src.read.untaint, fname, 1)
8
+ @@list << val if val
9
+ warn("loaded plugin: #{fname}")
10
+ rescue
11
+ warn($!)
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ attr_reader :api
18
+ def initialize(args)
19
+ @api = []
20
+ @@list.each do |klass|
21
+ begin
22
+ @api += klass.new(*args).api
23
+ rescue
24
+ warn($!)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,15 @@
1
+ module Process
2
+ def invoke(cmd)
3
+ begin
4
+ require 'rubygems'
5
+ require 'win32/process'
6
+ args = {
7
+ 'command_line' => cmd,
8
+ }
9
+ Process.create(args)
10
+ rescue LoadError
11
+ system(cmd + ' &')
12
+ end
13
+ end
14
+ module_function :invoke
15
+ end
@@ -0,0 +1,22 @@
1
+ require 'rbconfig'
2
+
3
+ module RbConfig
4
+ cmd = File.join(CONFIG['bindir'], CONFIG['ruby_install_name'])
5
+ CONFIG['ruby_command'] = cmd.sub(/.*\s.*/m, '"\&"')
6
+
7
+ def program_name
8
+ return (defined?(ExerbRuntime) && ExerbRuntime.filepath) || $0
9
+ end
10
+
11
+ def self_invoke_command
12
+ cmd = File.expand_path(program_name)
13
+ cmd.sub(/.*\s.*/m, '"\&"')
14
+ ext = Config::CONFIG['EXEEXT']
15
+ unless ext.length != 0 && program_name =~ /#{ext}$/
16
+ cmd = CONFIG['ruby_command'] + ' ' + cmd
17
+ end
18
+ return cmd
19
+ end
20
+
21
+ module_function :program_name, :self_invoke_command
22
+ end
@@ -0,0 +1,15 @@
1
+ class String
2
+ def randomize(len=128)
3
+ return Array.new(len).map{ self[rand(self.length)].chr }.join
4
+ end
5
+
6
+ def self.random(len=128, src=nil)
7
+ src ||=
8
+ [
9
+ 'a'..'z',
10
+ 'A'..'Z',
11
+ 0..9,
12
+ ].map{|v| v.to_a}.join + '!@#$%^&*()_-=,./'
13
+ return src.randomize(len)
14
+ end
15
+ end
@@ -0,0 +1,50 @@
1
+ require 'termios'
2
+
3
+ module Term
4
+ def countdown(time, *args, &block)
5
+ wait, br = args
6
+ if args[0].instance_of?(Hash)
7
+ wait = args[0][:wait]
8
+ br = args[0][:br]
9
+ end
10
+ wait ||= 0.05
11
+ br ||= '[\r\n]'
12
+ default = proc do |elapse|
13
+ t = time - elapse
14
+ t = 0 if t < 0
15
+ t *= 1000
16
+ $stdout.flush
17
+ printf("\r%6d", t.to_i)
18
+ end
19
+ block = default unless block
20
+
21
+ old = Termios.tcgetattr($stdin)
22
+ tio = Termios.tcgetattr($stdin)
23
+ tio.cc[Termios::VMIN] = 1
24
+ tio.cc[Termios::VTIME] = 0
25
+ tio.iflag &= ~Termios::ICRNL # see libcurses/screen/cbreak.c
26
+ tio.lflag &= ~Termios::ICANON
27
+ tio.lflag &= ~Termios::ECHO
28
+ Termios.tcsetattr($stdin, Termios::TCSANOW, tio)
29
+
30
+ begin
31
+ s = Time.now.to_f
32
+ e = s + time.to_f
33
+ while true
34
+ now = Time.now.to_f
35
+ block.call(now - s)
36
+ break if now >= e
37
+ sleep(wait)
38
+ s = $stdin.read_nonblock(1) rescue next
39
+ break if s =~ /#{br}/
40
+ return false
41
+ end
42
+ ensure
43
+ Termios.tcsetattr($stdin, Termios::TCSANOW, old)
44
+ end
45
+
46
+ return true
47
+ end
48
+
49
+ module_function :countdown
50
+ end
@@ -0,0 +1,80 @@
1
+ require 'thread'
2
+ require 'socket'
3
+ require 'timeout'
4
+ require 'webrick/config'
5
+ require 'webrick/log'
6
+
7
+ module WEBrick
8
+ class GenericServer
9
+ def start(&block)
10
+ raise ServerError, "already started." if @status != :Stop
11
+ server_type = @config[:ServerType] || SimpleServer
12
+
13
+ server_type.start{
14
+ @logger.info \
15
+ "#{self.class}#start: pid=#{$$} port=#{@config[:Port]}"
16
+ call_callback(:StartCallback)
17
+
18
+ @status = :Running
19
+ while @status == :Running
20
+ begin
21
+ if svrs = IO.select(@listeners, nil, nil, 2.0)
22
+ svrs[0].each{|svr|
23
+ @tokens.pop # blocks while no token is there.
24
+ if sock = accept_client(svr)
25
+ th = start_thread(sock, &block)
26
+ else
27
+ @tokens.push(nil)
28
+ end
29
+ }
30
+ end
31
+ rescue Errno::EBADF, IOError => ex
32
+ # if the listening socket was closed in GenericServer#shutdown,
33
+ # IO::select raise it.
34
+ rescue Exception => ex
35
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
36
+ @logger.error msg
37
+ end
38
+ end
39
+
40
+ @logger.info "going to shutdown ..."
41
+ call_callback(:StopCallback)
42
+ @logger.info "#{self.class}#start done."
43
+ @status = :Stop
44
+ }
45
+ end
46
+
47
+ private
48
+
49
+ def start_thread(sock, &block)
50
+ begin
51
+ Thread.current[:WEBrickSocket] = sock
52
+ begin
53
+ addr = sock.peeraddr
54
+ @logger.debug "accept: #{addr[3]}:#{addr[1]}"
55
+ rescue SocketError
56
+ @logger.debug "accept: <address unknown>"
57
+ raise
58
+ end
59
+ call_callback(:AcceptCallback, sock)
60
+ block ? block.call(sock) : run(sock)
61
+ rescue Errno::ENOTCONN
62
+ @logger.debug "Errno::ENOTCONN raised"
63
+ rescue ServerError => ex
64
+ msg = "#{ex.class}: #{ex.message}\n\t#{ex.backtrace[0]}"
65
+ @logger.error msg
66
+ rescue Exception => ex
67
+ @logger.error ex
68
+ ensure
69
+ @tokens.push(nil)
70
+ Thread.current[:WEBrickSocket] = nil
71
+ if addr
72
+ @logger.debug "close: #{addr[3]}:#{addr[1]}"
73
+ else
74
+ @logger.debug "close: <address unknown>"
75
+ end
76
+ sock.close
77
+ end
78
+ end
79
+ end # end of GenericServer
80
+ end
@@ -0,0 +1,125 @@
1
+ require 'rubygems'
2
+ require 'mechanize'
3
+ require 'logger'
4
+
5
+ module WWW
6
+ class Mechanize
7
+ class Method
8
+ attr_accessor :method, :domain, :verbose, :agent, :req
9
+
10
+ def initialize(method, conf={}, verbose=nil)
11
+ @method = method
12
+ @domain = @method[:type] + '://' + @method[:domain]
13
+ @verbose = verbose
14
+
15
+ # user agent
16
+ logger = conf[:logger] || (conf[:log] && Logger.new(conf[:log]))
17
+ @agent = WWW::Mechanize.new{|a| a.log = logger if logger}
18
+ @agent.ca_file = conf[:ssl_cert] || '/usr/share/ssl/cert.pem'
19
+ @agent.user_agent_alias = conf[:ua_alias] if conf[:ua_alias]
20
+ @agent.user_agent = conf[:ua] if conf[:ua]
21
+ auth = @method[:auth]
22
+ @agent.auth(auth[:user], auth[:pass]) if auth
23
+
24
+ # request methods
25
+ psend = proc{|rq,r| do_send(rq,r)}
26
+ @req = {
27
+ :get => psend,
28
+ :post => psend,
29
+ :form => proc{|rq,r| do_form(rq,r)},
30
+ :regexp => proc{|rq,r| do_parse(rq,r)},
31
+ }
32
+
33
+ return self
34
+ end
35
+
36
+ def do
37
+ warn("#{@method[:name]}: retrieve by #{@method[:type]}") if @verbose
38
+ result = { :obj => {} }
39
+
40
+ @method[:requests].each do |req|
41
+ begin
42
+ if req.is_a?(String)
43
+ result = @req[:get].call(req, result)
44
+ elsif req.is_a?(Proc)
45
+ result = req.call(self, req, result)
46
+ elsif req.is_a?(Hash)
47
+ key = @req.keys.find{|k| req.key?(k)}
48
+ raise 'invalid method' unless key
49
+ result = @req[key].call(req, result)
50
+ else
51
+ raise 'unknown method'
52
+ end
53
+ rescue => e
54
+ warn("#{e}: #{req.to_s}") if @verbose
55
+ end
56
+ end
57
+
58
+ return result
59
+ end
60
+
61
+ def do_send(req, result) # POST / GET
62
+ m = (req.is_a?(Hash) && req[:post]) ? :post : :get
63
+ uri = @domain + (req.is_a?(Hash) ? req[m] : req)
64
+ params = req.is_a?(Hash) ? req[:params] : {}
65
+ warn("#{m} #{uri}") if @verbose
66
+ result[:page] = @agent.send(m.to_s, uri, params || {}) # reflective
67
+ return result
68
+ end
69
+
70
+ def do_form(req, result) # form.submit
71
+ raise 'no page at WWW.Mechanize.Method.do_form' unless result[:page]
72
+
73
+ name = req[:form]
74
+ f = result[:page].forms.find{|v| v.name == name} if name.is_a?(String)
75
+ f = result[:page].forms[name] if name.is_a?(Integer)
76
+ raise 'failed at WWW.Mechanize.Method.do_form' unless f
77
+
78
+ f.action = req[:action] if req[:action]
79
+ f.set_fields(req[:fields])
80
+ warn("submit #{f.action}") if @verbose
81
+ result[:page] = f.submit
82
+ return result
83
+ end
84
+
85
+ def do_parse(req, result) # parse
86
+ raise 'no page at WWW.Mechanize.Method.do_parse' unless result[:page]
87
+
88
+ if result[:page].body =~ /#{req[:regexp]}/im
89
+ warn("parse #{req[:regexp]}") if @verbose
90
+ if req[:result].is_a?(Hash)
91
+ req[:result].each do |key, val|
92
+ result[:obj][key] = $~[val]
93
+ end
94
+ elsif req[:result].is_a?(String)
95
+ $~.shift if $~.size > 1
96
+ result[:obj][req[:result].to_sym] = $~
97
+ else
98
+ $~.shift if $~.size > 1
99
+ result[:obj] = $~
100
+ end
101
+ else
102
+ raise 'parse failed at WWW.Mechanize.Method.do_parse'
103
+ end
104
+
105
+ return result
106
+ end
107
+ end
108
+
109
+ def self.get(methods, opt)
110
+ v = opt[:verbose]
111
+ r = opt[:require]
112
+ c = opt[:config]
113
+
114
+ result = { :obj => {} }
115
+ methods = [ methods ] unless methods.is_a?(Array)
116
+ methods.each do |val|
117
+ m = Method.new(val, c, v)
118
+ result = m.do
119
+ break if r.all?{|k| result[:obj][k]}
120
+ end
121
+
122
+ return result
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,7 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe "GnnRblibs" do
4
+ it "fails" do
5
+ fail "hey buddy, you should probably rename this file and start specing for real"
6
+ end
7
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
@@ -0,0 +1,8 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'spec'
4
+ require 'spec/autorun'
5
+
6
+ Spec::Runner.configure do |config|
7
+
8
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gnn-rblibs
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - tarao
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-11-28 00:00:00 +00:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rspec
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.9
24
+ version:
25
+ description: Some Ruby tweaks for file operations, commandline parsers, etc.
26
+ email: tarao.gnn@gmail.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .document
36
+ - .gitignore
37
+ - LICENSE
38
+ - README.rdoc
39
+ - Rakefile
40
+ - VERSION
41
+ - gnn-rblibs.gemspec
42
+ - lib/dir/each_leaf.rb
43
+ - lib/file/kind.rb
44
+ - lib/file/observer.rb
45
+ - lib/fileutils/sync.rb
46
+ - lib/getopt.rb
47
+ - lib/loadconf.rb
48
+ - lib/plugin.rb
49
+ - lib/process/invoke.rb
50
+ - lib/rbconfig/command.rb
51
+ - lib/string/random.rb
52
+ - lib/term/countdown.rb
53
+ - lib/webrick/single_thread_server.rb
54
+ - lib/www/mechanize/get.rb
55
+ - spec/gnn-rblibs_spec.rb
56
+ - spec/spec.opts
57
+ - spec/spec_helper.rb
58
+ has_rdoc: true
59
+ homepage: http://github.com/tarao/gnn-rblibs
60
+ licenses: []
61
+
62
+ post_install_message:
63
+ rdoc_options:
64
+ - --charset=UTF-8
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ required_rubygems_version: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - ">="
76
+ - !ruby/object:Gem::Version
77
+ version: "0"
78
+ version:
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.5
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Some Ruby tweaks
86
+ test_files:
87
+ - spec/spec_helper.rb
88
+ - spec/gnn-rblibs_spec.rb