emasaka-termtter 1.0.7.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +4 -0
- data/README.rdoc +100 -0
- data/Rakefile +55 -0
- data/bin/kill_termtter +22 -0
- data/bin/termtter +6 -0
- data/lib/plugins/addspace.rb +27 -0
- data/lib/plugins/april_fool.rb +15 -0
- data/lib/plugins/bomb.rb +39 -0
- data/lib/plugins/clear.rb +14 -0
- data/lib/plugins/command_plus.rb +47 -0
- data/lib/plugins/confirm.rb +12 -0
- data/lib/plugins/cool.rb +10 -0
- data/lib/plugins/countter.rb +23 -0
- data/lib/plugins/devel.rb +18 -0
- data/lib/plugins/direct_messages.rb +36 -0
- data/lib/plugins/en2ja.rb +11 -0
- data/lib/plugins/english.rb +25 -0
- data/lib/plugins/erb.rb +17 -0
- data/lib/plugins/exec_and_update.rb +14 -0
- data/lib/plugins/expand-tinyurl.rb +33 -0
- data/lib/plugins/fib.rb +28 -0
- data/lib/plugins/fib_filter.rb +14 -0
- data/lib/plugins/filter.rb +69 -0
- data/lib/plugins/graduatter.rb +8 -0
- data/lib/plugins/grass.rb +27 -0
- data/lib/plugins/group.rb +64 -0
- data/lib/plugins/growl.rb +52 -0
- data/lib/plugins/growl2.rb +143 -0
- data/lib/plugins/hatebu.rb +59 -0
- data/lib/plugins/history.rb +93 -0
- data/lib/plugins/ignore.rb +19 -0
- data/lib/plugins/keyword.rb +18 -0
- data/lib/plugins/l2.rb +25 -0
- data/lib/plugins/log.rb +73 -0
- data/lib/plugins/me.rb +10 -0
- data/lib/plugins/modify_arg_hook_sample.rb +7 -0
- data/lib/plugins/msagent.rb +38 -0
- data/lib/plugins/multi_reply.rb +27 -0
- data/lib/plugins/notify-send.rb +22 -0
- data/lib/plugins/notify-send2.rb +52 -0
- data/lib/plugins/open_url.rb +59 -0
- data/lib/plugins/otsune.rb +21 -0
- data/lib/plugins/outputz.rb +33 -0
- data/lib/plugins/pause.rb +3 -0
- data/lib/plugins/post_exec_hook_sample.rb +9 -0
- data/lib/plugins/pre_exec_hook_sample.rb +9 -0
- data/lib/plugins/primes.rb +30 -0
- data/lib/plugins/quicklook.rb +41 -0
- data/lib/plugins/random.rb +23 -0
- data/lib/plugins/reblog.rb +40 -0
- data/lib/plugins/reload.rb +3 -0
- data/lib/plugins/reply.rb +8 -0
- data/lib/plugins/retweet.rb +46 -0
- data/lib/plugins/reverse.rb +13 -0
- data/lib/plugins/say.rb +26 -0
- data/lib/plugins/scrape.rb +41 -0
- data/lib/plugins/screen-notify.rb +20 -0
- data/lib/plugins/screen.rb +24 -0
- data/lib/plugins/shell.rb +14 -0
- data/lib/plugins/shorturl_on_update.rb +36 -0
- data/lib/plugins/sl.rb +48 -0
- data/lib/plugins/spam.rb +16 -0
- data/lib/plugins/standard_plugins.rb +519 -0
- data/lib/plugins/stdout.rb +83 -0
- data/lib/plugins/storage.rb +55 -0
- data/lib/plugins/storage/DB.rb +37 -0
- data/lib/plugins/storage/status.rb +83 -0
- data/lib/plugins/storage/status_mook.rb +30 -0
- data/lib/plugins/switch_user.rb +22 -0
- data/lib/plugins/system_status.rb +33 -0
- data/lib/plugins/timer.rb +18 -0
- data/lib/plugins/translation.rb +38 -0
- data/lib/plugins/typable_id.rb +94 -0
- data/lib/plugins/update_editor.rb +53 -0
- data/lib/plugins/update_filter.rb +30 -0
- data/lib/plugins/uri-open.rb +66 -0
- data/lib/plugins/wassr_post.rb +22 -0
- data/lib/plugins/yhara.rb +148 -0
- data/lib/plugins/yhara_filter.rb +8 -0
- data/lib/plugins/yonda.rb +21 -0
- data/lib/termtter.rb +38 -0
- data/lib/termtter/api.rb +57 -0
- data/lib/termtter/client.rb +370 -0
- data/lib/termtter/command.rb +80 -0
- data/lib/termtter/config.rb +68 -0
- data/lib/termtter/config_setup.rb +38 -0
- data/lib/termtter/connection.rb +41 -0
- data/lib/termtter/hook.rb +31 -0
- data/lib/termtter/optparse.rb +14 -0
- data/lib/termtter/system_extensions.rb +161 -0
- data/lib/termtter/task.rb +17 -0
- data/lib/termtter/task_manager.rb +116 -0
- data/lib/termtter/version.rb +4 -0
- data/spec/plugins/cool_spec.rb +10 -0
- data/spec/plugins/english_spec.rb +19 -0
- data/spec/plugins/fib_spec.rb +15 -0
- data/spec/plugins/filter_spec.rb +18 -0
- data/spec/plugins/pause_spec.rb +8 -0
- data/spec/plugins/primes_spec.rb +15 -0
- data/spec/plugins/shell_spec.rb +10 -0
- data/spec/plugins/sl_spec.rb +8 -0
- data/spec/plugins/spam_spec.rb +4 -0
- data/spec/plugins/standard_plugins_spec.rb +23 -0
- data/spec/plugins/storage/DB_spec.rb +12 -0
- data/spec/plugins/storage/status_spec.rb +24 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/termtter/client_spec.rb +255 -0
- data/spec/termtter/command_spec.rb +107 -0
- data/spec/termtter/config_spec.rb +111 -0
- data/spec/termtter/hook_spec.rb +78 -0
- data/spec/termtter/task_manager_spec.rb +78 -0
- data/spec/termtter/task_spec.rb +22 -0
- data/spec/termtter_spec.rb +29 -0
- data/test/friends_timeline.json +5 -0
- data/test/search.json +8 -0
- metadata +210 -0
@@ -0,0 +1,68 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
#
|
3
|
+
module Termtter
|
4
|
+
class Config
|
5
|
+
def initialize
|
6
|
+
@store = Hash.new(:undefined)
|
7
|
+
end
|
8
|
+
|
9
|
+
def inspect
|
10
|
+
@store.inspect
|
11
|
+
end
|
12
|
+
|
13
|
+
# set_default :: (Symbol | String) -> a -> IO ()
|
14
|
+
def set_default(name, value)
|
15
|
+
match_p, init, last = *name.to_s.match(/^(.+)\.([^\.]+)$/)
|
16
|
+
if match_p
|
17
|
+
tmp = eval(init)
|
18
|
+
if tmp.__refer__(last.to_sym).empty?
|
19
|
+
tmp.__assign__(last.to_sym, value)
|
20
|
+
end
|
21
|
+
else
|
22
|
+
__assign__(name.to_sym, value) if __refer__(name.to_sym).empty?
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# empty? :: Boolean
|
27
|
+
def empty?
|
28
|
+
@store.empty?
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(name, *args)
|
32
|
+
case name.to_s
|
33
|
+
when /(.*)=$/
|
34
|
+
__assign__($1.to_sym, args.first)
|
35
|
+
else
|
36
|
+
__refer__(name.to_sym)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# __assign__ :: Symbol -> a -> IO ()
|
41
|
+
def __assign__(name, value)
|
42
|
+
@store[name] = value
|
43
|
+
end
|
44
|
+
|
45
|
+
# __refer__ :: Symbol -> IO a
|
46
|
+
def __refer__(name)
|
47
|
+
@store[name] == :undefined ? @store[name] = Termtter::Config.new : @store[name]
|
48
|
+
end
|
49
|
+
|
50
|
+
def __values__
|
51
|
+
@store.dup
|
52
|
+
end
|
53
|
+
|
54
|
+
__instance = self.new
|
55
|
+
(class << self; self end).
|
56
|
+
__send__(:define_method, :instance) { __instance }
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def config
|
61
|
+
Termtter::Config.instance
|
62
|
+
end
|
63
|
+
|
64
|
+
def configatron
|
65
|
+
# remove this method until Termtter-1.2.0
|
66
|
+
warn "configatron method will be removed. Use config instead. (#{caller.first})"
|
67
|
+
Termtter::Config.instance
|
68
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
module ConfigSetup
|
5
|
+
module_function
|
6
|
+
def run
|
7
|
+
ui = create_highline
|
8
|
+
username = ui.ask('your twitter username: ')
|
9
|
+
password = ui.ask('your twitter password: ') { |q| q.echo = false }
|
10
|
+
|
11
|
+
Dir.mkdir(Termtter::CONF_DIR) unless File.exists?(Termtter::CONF_DIR)
|
12
|
+
File.open(Termtter::CONF_FILE, 'w') {|io|
|
13
|
+
io.puts '# -*- coding: utf-8 -*-'
|
14
|
+
|
15
|
+
io.puts
|
16
|
+
io.puts "config.user_name = '#{username}'"
|
17
|
+
io.puts "config.password = '#{password}'"
|
18
|
+
io.puts "#config.update_interval = 120"
|
19
|
+
io.puts "#config.proxy.host = 'proxy host'"
|
20
|
+
io.puts "#config.proxy.port = '8080'"
|
21
|
+
io.puts "#config.proxy.user_name = 'proxy user'"
|
22
|
+
io.puts "#config.proxy.password = 'proxy password'"
|
23
|
+
io.puts
|
24
|
+
plugins = Dir.glob(File.expand_path(File.dirname(__FILE__) + "/../plugins/*.rb")).map {|f|
|
25
|
+
f.match(%r|lib/plugins/(.*?).rb$|)[1]
|
26
|
+
}
|
27
|
+
plugins -= %w[stdout standard_plugins]
|
28
|
+
plugins.each do |p|
|
29
|
+
io.puts "#plugin '#{p}'"
|
30
|
+
end
|
31
|
+
io.puts
|
32
|
+
io.puts "# vim: set filetype=ruby"
|
33
|
+
}
|
34
|
+
puts "generated: ~/.termtter/config"
|
35
|
+
puts "enjoy!"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
class Connection
|
5
|
+
attr_reader :protocol, :port, :proxy_uri
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
unless config.proxy.empty?
|
9
|
+
@proxy_host = config.proxy.host
|
10
|
+
@proxy_port = config.proxy.port
|
11
|
+
@proxy_user = config.proxy.user_name
|
12
|
+
@proxy_password = config.proxy.password
|
13
|
+
@proxy_uri = nil
|
14
|
+
@enable_ssl = config.enable_ssl
|
15
|
+
end
|
16
|
+
@protocol = "http"
|
17
|
+
@port = 80
|
18
|
+
|
19
|
+
if @proxy_host
|
20
|
+
@http_class = Net::HTTP::Proxy(@proxy_host, @proxy_port,
|
21
|
+
@proxy_user, @proxy_password)
|
22
|
+
@proxy_uri = "http://" + @proxy_host + ":" + @proxy_port + "/"
|
23
|
+
else
|
24
|
+
@http_class = Net::HTTP
|
25
|
+
end
|
26
|
+
|
27
|
+
if @enable_ssl
|
28
|
+
@protocol = "https"
|
29
|
+
@port = 443
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def start(host, port, &block)
|
34
|
+
http = @http_class.new(host, port)
|
35
|
+
http.use_ssl = @enable_ssl
|
36
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE if http.use_ssl?
|
37
|
+
http.start(&block)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
class Hook
|
5
|
+
attr_accessor :name, :points, :exec_proc
|
6
|
+
|
7
|
+
def initialize(args)
|
8
|
+
raise ArgumentError, ":name is not given." unless args.has_key?(:name)
|
9
|
+
@name = args[:name].to_sym
|
10
|
+
@points = args[:points] || [args[:point]].compact
|
11
|
+
@exec_proc = args[:exec_proc] || args[:exec] || lambda {}
|
12
|
+
end
|
13
|
+
|
14
|
+
def match?(point)
|
15
|
+
!points.select{|pt|
|
16
|
+
case pt
|
17
|
+
when String, Symbol
|
18
|
+
pt.to_s == point.to_s
|
19
|
+
when Regexp
|
20
|
+
(pt =~ point.to_s) ? true : false
|
21
|
+
else
|
22
|
+
false
|
23
|
+
end
|
24
|
+
}.empty?
|
25
|
+
end
|
26
|
+
|
27
|
+
def call(*args)
|
28
|
+
self.exec_proc.call(*args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
OptionParser.new { |opt|
|
2
|
+
opt.on('-f', '--file config_file', 'Set path to configfile') do |val|
|
3
|
+
config.system.__assign__(:conf_file, val)
|
4
|
+
end
|
5
|
+
opt.on('-t', '--termtter-directory directory', 'Set termtter directory') do |val|
|
6
|
+
config.system.__assign__(:conf_dir, val)
|
7
|
+
end
|
8
|
+
opt.on('-d', '--devel', 'Start in developer mode') do |flg|
|
9
|
+
config.system.__assign__(:devel, true) if flg
|
10
|
+
end
|
11
|
+
|
12
|
+
Version = Termtter::VERSION
|
13
|
+
opt.parse!(ARGV)
|
14
|
+
}
|
@@ -0,0 +1,161 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
def plugin(name, init = {})
|
4
|
+
unless init.empty?
|
5
|
+
init.each do |key, value|
|
6
|
+
config.plugins.__refer__(name.to_sym).__assign__(key.to_sym, value)
|
7
|
+
end
|
8
|
+
end
|
9
|
+
load "plugins/#{name}.rb"
|
10
|
+
rescue Exception => e
|
11
|
+
Termtter::Client.handle_error(e)
|
12
|
+
end
|
13
|
+
|
14
|
+
def filter(name, init = {})
|
15
|
+
warn "filter method will be removed. Use plugin instead."
|
16
|
+
plugin(name, init)
|
17
|
+
end
|
18
|
+
|
19
|
+
require 'dl/import'
|
20
|
+
module Readline
|
21
|
+
begin
|
22
|
+
module LIBREADLINE
|
23
|
+
if DL.const_defined? :Importable
|
24
|
+
extend DL::Importable
|
25
|
+
else
|
26
|
+
extend DL::Importer
|
27
|
+
end
|
28
|
+
pathes = Array(ENV['TERMTTER_EXT_LIB'] || [
|
29
|
+
'/opt/local/lib/libreadline.dylib',
|
30
|
+
'/usr/lib/libreadline.so',
|
31
|
+
'/usr/local/lib/libreadline.so',
|
32
|
+
File.join(Gem.bindir, 'readline.dll')
|
33
|
+
])
|
34
|
+
dlload(pathes.find { |path| File.exist?(path)})
|
35
|
+
extern 'int rl_refresh_line(int, int)'
|
36
|
+
end
|
37
|
+
def self.refresh_line
|
38
|
+
LIBREADLINE.rl_refresh_line(0, 0)
|
39
|
+
end
|
40
|
+
rescue Exception
|
41
|
+
def self.refresh_line;end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def win?
|
46
|
+
RUBY_PLATFORM.downcase =~ /mswin(?!ce)|mingw|bccwin/
|
47
|
+
end
|
48
|
+
|
49
|
+
if win?
|
50
|
+
require 'iconv'
|
51
|
+
require 'Win32API'
|
52
|
+
$wGetACP = Win32API.new('kernel32','GetACP','','I')
|
53
|
+
|
54
|
+
module Readline
|
55
|
+
$iconv_sj_to_u8 = Iconv.new('UTF-8', "CP#{$wGetACP.call()}")
|
56
|
+
alias :old_readline :readline
|
57
|
+
def readline(*a)
|
58
|
+
str = old_readline(*a)
|
59
|
+
out = ''
|
60
|
+
loop do
|
61
|
+
begin
|
62
|
+
out << $iconv_sj_to_u8.iconv(str)
|
63
|
+
break
|
64
|
+
rescue Iconv::Failure
|
65
|
+
out << "#{$!.success}?"
|
66
|
+
str = $!.failed[1..-1]
|
67
|
+
end
|
68
|
+
end
|
69
|
+
return out
|
70
|
+
end
|
71
|
+
module_function :old_readline, :readline
|
72
|
+
end
|
73
|
+
|
74
|
+
$wSetConsoleTextAttribute = Win32API.new('kernel32','SetConsoleTextAttribute','II','I')
|
75
|
+
$wGetConsoleScreenBufferInfo = Win32API.new("kernel32", "GetConsoleScreenBufferInfo", ['l', 'p'], 'i')
|
76
|
+
$wGetStdHandle = Win32API.new('kernel32','GetStdHandle','I','I')
|
77
|
+
$wGetACP = Win32API.new('kernel32','GetACP','','I')
|
78
|
+
|
79
|
+
$hStdOut = $wGetStdHandle.call(0xFFFFFFF5)
|
80
|
+
lpBuffer = ' ' * 22
|
81
|
+
$wGetConsoleScreenBufferInfo.call($hStdOut, lpBuffer)
|
82
|
+
$oldColor = lpBuffer.unpack('SSSSSssssSS')[4]
|
83
|
+
|
84
|
+
$colorMap = {
|
85
|
+
0 => 0x07|0x00|0x00|0x00, # black/white
|
86
|
+
37 => 0x08|0x00|0x00|0x00, # white/intensity
|
87
|
+
31 => 0x04|0x08|0x00|0x00, # red/red
|
88
|
+
32 => 0x02|0x08|0x00|0x00, # green/green
|
89
|
+
33 => 0x06|0x08|0x00|0x00, # yellow/yellow
|
90
|
+
34 => 0x01|0x08|0x00|0x00, # blue/blue
|
91
|
+
35 => 0x05|0x08|0x00|0x00, # magenta/purple
|
92
|
+
36 => 0x03|0x08|0x00|0x00, # cyan/aqua
|
93
|
+
39 => 0x07, # default
|
94
|
+
40 => 0x00|0x00|0xf0|0x00, # background:white
|
95
|
+
41 => 0x07|0x00|0x40|0x00, # background:red
|
96
|
+
42 => 0x07|0x00|0x20|0x00, # background:green
|
97
|
+
43 => 0x07|0x00|0x60|0x00, # background:yellow
|
98
|
+
44 => 0x07|0x00|0x10|0x00, # background:blue
|
99
|
+
45 => 0x07|0x00|0x50|0x80, # background:magenta
|
100
|
+
46 => 0x07|0x00|0x30|0x80, # background:cyan
|
101
|
+
47 => 0x07|0x00|0x70|0x80, # background:gray
|
102
|
+
49 => 0x70, # default
|
103
|
+
90 => 0x07|0x00|0x00|0x00, # erase/white
|
104
|
+
}
|
105
|
+
$iconv_u8_to_sj = Iconv.new("CP#{$wGetACP.call()}", 'UTF-8')
|
106
|
+
def print(str)
|
107
|
+
str.to_s.gsub("\xef\xbd\x9e", "\xe3\x80\x9c").split(/(\e\[\d*[a-zA-Z])/).each do |token|
|
108
|
+
case token
|
109
|
+
when /\e\[(\d+)m/
|
110
|
+
$wSetConsoleTextAttribute.call $hStdOut, $colorMap[$1.to_i].to_i
|
111
|
+
when /\e\[\d*[a-zA-Z]/
|
112
|
+
# do nothing
|
113
|
+
else
|
114
|
+
loop do
|
115
|
+
begin
|
116
|
+
STDOUT.print $iconv_u8_to_sj.iconv(token)
|
117
|
+
break
|
118
|
+
rescue Iconv::Failure
|
119
|
+
STDOUT.print "#{$!.success}?"
|
120
|
+
token = $!.failed[1..-1]
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
$wSetConsoleTextAttribute.call $hStdOut, $oldColor
|
126
|
+
$iconv_u8_to_sj.iconv(nil)
|
127
|
+
end
|
128
|
+
def puts(str)
|
129
|
+
print str
|
130
|
+
STDOUT.puts
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
unless Array.instance_methods.include?('take')
|
135
|
+
class Array
|
136
|
+
def take(n) self[0...n] end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
unless Symbol.instance_methods.include?('to_proc')
|
141
|
+
class Symbol
|
142
|
+
def to_proc
|
143
|
+
Proc.new { |*args| args.shift.__send__(self, *args) }
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
require 'highline'
|
149
|
+
def create_highline
|
150
|
+
HighLine.track_eof = false
|
151
|
+
if $stdin.respond_to?(:getbyte) # for ruby1.9
|
152
|
+
require 'delegate'
|
153
|
+
stdin_for_highline = SimpleDelegator.new($stdin)
|
154
|
+
def stdin_for_highline.getc
|
155
|
+
getbyte
|
156
|
+
end
|
157
|
+
else
|
158
|
+
stdin_for_highline = $stdin
|
159
|
+
end
|
160
|
+
HighLine.new(stdin_for_highline)
|
161
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
class Task
|
5
|
+
attr_accessor :name, :exec_at, :exec_proc, :interval, :work
|
6
|
+
def initialize(args = {}, &block)
|
7
|
+
@name = args[:name]
|
8
|
+
@exec_at = Time.now + (args[:after] || 0)
|
9
|
+
@interval = args[:interval]
|
10
|
+
@exec_proc = block || lambda {}
|
11
|
+
@work = true
|
12
|
+
end
|
13
|
+
def execute
|
14
|
+
exec_proc.call(self) if work
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,116 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
|
3
|
+
module Termtter
|
4
|
+
class TaskManager
|
5
|
+
|
6
|
+
INTERVAL = 1
|
7
|
+
|
8
|
+
def initialize()
|
9
|
+
@tasks = {}
|
10
|
+
@work = true
|
11
|
+
@mutex = Mutex.new
|
12
|
+
@pause = false
|
13
|
+
end
|
14
|
+
|
15
|
+
def pause
|
16
|
+
@pause = true
|
17
|
+
end
|
18
|
+
|
19
|
+
def resume
|
20
|
+
@pause = false
|
21
|
+
end
|
22
|
+
|
23
|
+
def kill
|
24
|
+
@work = false
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
Thread.new do
|
29
|
+
while @work
|
30
|
+
step unless @pause
|
31
|
+
sleep INTERVAL
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def step
|
37
|
+
pull_due_tasks.each do |task|
|
38
|
+
invoke_and_wait do
|
39
|
+
task.execute
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def invoke_later
|
45
|
+
Thread.new do
|
46
|
+
invoke_and_wait do
|
47
|
+
yield
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def invoke_and_wait(&block)
|
53
|
+
synchronize do
|
54
|
+
begin
|
55
|
+
yield
|
56
|
+
rescue Exception => e
|
57
|
+
Termtter::Client.handle_error(e)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def add_task(args = {}, &block)
|
63
|
+
synchronize do
|
64
|
+
task = Task.new(args, &block)
|
65
|
+
@tasks[task.name || task.object_id] = task
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def get_task(key)
|
70
|
+
synchronize do
|
71
|
+
@tasks[key]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def delete_task(key)
|
76
|
+
synchronize do
|
77
|
+
@tasks.delete(key)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def synchronize
|
84
|
+
unless Thread.current == @thread_in_sync
|
85
|
+
@mutex.synchronize do
|
86
|
+
@thread_in_sync = Thread.current
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
else
|
90
|
+
yield
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def pull_due_tasks()
|
95
|
+
synchronize do
|
96
|
+
time_now = Time.now
|
97
|
+
due_tasks = []
|
98
|
+
@tasks.delete_if do |key, task|
|
99
|
+
if task.work && task.exec_at <= time_now
|
100
|
+
due_tasks << task
|
101
|
+
if task.interval
|
102
|
+
task.exec_at = time_now + task.interval
|
103
|
+
false
|
104
|
+
else
|
105
|
+
true
|
106
|
+
end
|
107
|
+
else
|
108
|
+
false
|
109
|
+
end
|
110
|
+
end
|
111
|
+
return due_tasks
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|