gnn-rblibs 0.0.1

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.
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