snarl-snp 0.1.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.rdoc +86 -4
- data/Rakefile +4 -3
- data/VERSION +1 -1
- data/YAML.rdoc +197 -0
- data/bin/snarl_snp +112 -0
- data/{GUIDE.rdoc.ja → doc-ja/GUIDE.rdoc.ja} +0 -0
- data/{README.rdoc.ja → doc-ja/README.rdoc.ja} +94 -29
- data/doc-ja/YAML.rdoc.ja +200 -0
- data/exsample/yahoo_weather.rb +18 -4
- data/lib/snarl/autotest.rb +7 -77
- data/lib/snarl/snp.rb +4 -4
- data/lib/snarl/snp/action.rb +15 -11
- data/lib/snarl/snp/autosnp.rb +69 -0
- data/lib/snarl/snp/config.rb +109 -17
- data/lib/snarl/snp/error.rb +7 -6
- data/lib/snarl/snp/request.rb +31 -21
- data/lib/snarl/snp/response.rb +1 -0
- data/lib/snarl/snp/snp.rb +56 -41
- data/lib/snarl/snp/snp_procedure.rb +105 -0
- data/snarl-snp.gemspec +21 -15
- data/spec/bin/snarl_snp_spec.rb +91 -0
- data/spec/snp/action_spec.rb +149 -86
- data/spec/snp/config_spec.rb +181 -37
- data/spec/snp/real_connection_spec.rb +295 -0
- data/spec/snp/request_spec.rb +40 -10
- data/spec/snp/snp_procedure_spec.rb +226 -0
- data/spec/snp/snp_spec.rb +216 -193
- data/spec/spec_helper.rb +6 -4
- metadata +22 -27
- data/spec/exsample/data/weather_yahoo_co_jp.html +0 -608
- data/spec/exsample/yahoo_weather_spec.rb +0 -22
data/lib/snarl/snp.rb
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'socket'
|
2
|
-
|
2
|
+
require 'yaml'
|
3
3
|
$LOAD_PATH.unshift(File.dirname(File.expand_path(__FILE__)))
|
4
4
|
|
5
5
|
require 'snp/action'
|
6
|
-
require 'snp/
|
6
|
+
require 'snp/snp_procedure'
|
7
|
+
require 'snp/config'
|
7
8
|
require 'snp/request'
|
8
9
|
require 'snp/response'
|
9
10
|
require 'snp/error'
|
10
|
-
require 'snp/
|
11
|
-
# require 'snp/addon'
|
11
|
+
require 'snp/snp'
|
data/lib/snarl/snp/action.rb
CHANGED
@@ -13,9 +13,10 @@ class Snarl
|
|
13
13
|
#
|
14
14
|
# Snarl sends back a casual error when +app+ is already registered.
|
15
15
|
# It is treated as SNP::SNPError::Casual::SNP_ERROR_ALREADY_REGISTERED.
|
16
|
-
def register(app=nil)
|
17
|
-
|
18
|
-
|
16
|
+
def register(app = nil)
|
17
|
+
# when self['app'] == nil/unset and register(nil), SNARL receives SNP_ERROR_BAD_PACKET
|
18
|
+
self['app'] = app if app
|
19
|
+
cmds = {:action => 'register', :app => self['app']}
|
19
20
|
request(Request.new(cmds))
|
20
21
|
end
|
21
22
|
alias :app= :register
|
@@ -33,8 +34,8 @@ class Snarl
|
|
33
34
|
def add_class(classid, classtitle=nil)
|
34
35
|
# TODO: add_class(app=nil, classid, classtitle=nil)
|
35
36
|
# type=SNP#?version=1.0#?action=add_class#?class=t returns (107) Bad Packet
|
36
|
-
raise "#{self}#register(appname)
|
37
|
-
cmds = {:action => 'add_class', :app =>
|
37
|
+
raise "registering is required. #{self}#register(appname) before #add_class" unless self['app']
|
38
|
+
cmds = {:action => 'add_class', :app => self['app'], :class => classid.to_s, :title => classtitle}
|
38
39
|
request(Request.new(cmds))
|
39
40
|
end
|
40
41
|
|
@@ -66,7 +67,7 @@ class Snarl
|
|
66
67
|
# Snarl sends back a casual error when +app+ is not registered.
|
67
68
|
# It is treated as SNP::SNPError::Casual::SNP_ERROR_NOT_REGISTERED.
|
68
69
|
def unregister(app=nil)
|
69
|
-
app = app ||
|
70
|
+
app = app || self['app']
|
70
71
|
raise "#{self}#unregister requires appname." unless app
|
71
72
|
cmds = {:action => 'unregister', :app => app}
|
72
73
|
request(Request.new(cmds))
|
@@ -126,11 +127,14 @@ class Snarl
|
|
126
127
|
res[command] = keyhash_value if keyhash_value
|
127
128
|
end
|
128
129
|
res[:action] = 'notification'
|
129
|
-
res[:app] =
|
130
|
-
res[:
|
131
|
-
res[:
|
132
|
-
res[:
|
133
|
-
|
130
|
+
res[:app] = self['app'] if (res[:app].nil? && self['app']) # default notification
|
131
|
+
res[:title] = (res[:title] || self['title'] || DEFAULT_TITLE)
|
132
|
+
res[:timeout] = (res[:timeout] || self['timeout'] || DEFAULT_TIMEOUT)
|
133
|
+
if res[:icon] then
|
134
|
+
res[:icon] = icon(res[:icon])
|
135
|
+
elsif self['icon'] then
|
136
|
+
res[:icon] = self['icon']
|
137
|
+
end
|
134
138
|
return res
|
135
139
|
end
|
136
140
|
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require 'snp'
|
2
|
+
class Snarl
|
3
|
+
class SNP
|
4
|
+
module AutoSNP
|
5
|
+
@host=nil
|
6
|
+
@port=nil
|
7
|
+
@icondir=nil
|
8
|
+
@icon_ok=nil
|
9
|
+
@icon_fail=nil
|
10
|
+
@icon_pending=nil
|
11
|
+
@timeout_ok=nil
|
12
|
+
@timeout_fail=nil
|
13
|
+
|
14
|
+
attr_accessor :host, :port
|
15
|
+
attr_writer :icondir, :icon_ok, :icon_fail, :icon_pending, :timeout_ok, :timeout_fail
|
16
|
+
|
17
|
+
def snp
|
18
|
+
Snarl::SNP.load(<<YAML)
|
19
|
+
host : #{host}
|
20
|
+
port : #{port}
|
21
|
+
app : Autotest::Snarl
|
22
|
+
"class" :
|
23
|
+
- ['green', 'test ok']
|
24
|
+
- ['red', 'test fail']
|
25
|
+
- ['yellow', 'test pending']
|
26
|
+
- ['info', 'system message']
|
27
|
+
iconset :
|
28
|
+
green : #{File.join(icondir, icon_ok)}
|
29
|
+
red : #{File.join(icondir, icon_fail)}
|
30
|
+
yellow : #{File.join(icondir, icon_pending)}
|
31
|
+
YAML
|
32
|
+
end
|
33
|
+
|
34
|
+
# Windows Snarl shortcut's "working folder" (left click property)
|
35
|
+
# %HOME%\Application Data\full phat\snarl\styles
|
36
|
+
def icondir ; @icondir ||= './' ; end
|
37
|
+
|
38
|
+
# %HOME%\Application Data\full phat\snarl\styles\ok.png works fine
|
39
|
+
def icon_ok ; @icon_ok ||= "ok.png" ; end
|
40
|
+
def icon_fail ; @icon_fail ||= "fail.png" ; end
|
41
|
+
def icon_pending ; @icon_pending ||= "pending.png" ; end
|
42
|
+
|
43
|
+
def timeout_ok ; @timeout_ok ||= 5 ; end
|
44
|
+
def timeout_fail ; @timeout_fail ||= 10 ; end
|
45
|
+
|
46
|
+
def timeout(state)
|
47
|
+
case state
|
48
|
+
when :green then timeout_ok.to_i
|
49
|
+
when :red then timeout_fail.to_i
|
50
|
+
else 5
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def classname(state)
|
55
|
+
state.to_s
|
56
|
+
end
|
57
|
+
|
58
|
+
def snarl(title, text, state)
|
59
|
+
snp.notification(
|
60
|
+
:title => title,
|
61
|
+
:text => text,
|
62
|
+
:icon => state.to_s,
|
63
|
+
:timeout => timeout(state),
|
64
|
+
:class => classname(state)
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
data/lib/snarl/snp/config.rb
CHANGED
@@ -1,31 +1,123 @@
|
|
1
|
-
|
2
|
-
# when config file exists, require this config
|
3
1
|
class Snarl
|
4
2
|
class SNP
|
5
3
|
class Config
|
6
4
|
|
7
5
|
DEFAULT_HOST = '127.0.0.1'
|
8
6
|
DEFAULT_PORT = 9887
|
9
|
-
@host = nil
|
10
|
-
@port = nil
|
11
7
|
|
12
|
-
def
|
13
|
-
@
|
14
|
-
|
15
|
-
def self.host=(v)
|
16
|
-
@host = if v then v.to_s else nil end
|
8
|
+
def initialize
|
9
|
+
@config = {}
|
10
|
+
default_config
|
17
11
|
end
|
18
12
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
13
|
+
attr_reader :config # mainly for debug
|
14
|
+
|
15
|
+
def default_config
|
16
|
+
self['host'] = if $SAFE > 0 then DEFAULT_HOST else ENV['SNARL_HOST'] || DEFAULT_HOST end
|
17
|
+
self['port'] = if $SAFE > 0 then DEFAULT_PORT else ENV['SNARL_PORT'] || DEFAULT_PORT end
|
24
18
|
end
|
19
|
+
private :default_config
|
20
|
+
|
21
|
+
def []=(k, v) ; Normalize.store(k, v, @config) ; end
|
22
|
+
def [](k) ; @config[k.to_s] ; end
|
23
|
+
def reset ; @config = {} ; end
|
24
|
+
def to_yaml ; @config.to_yaml ; end
|
25
|
+
|
26
|
+
class Normalize
|
27
|
+
|
28
|
+
def self.store(k, v, hash)
|
29
|
+
nkey, nvalue = new(k, v).normalize
|
30
|
+
hash.store(nkey, nvalue) if nkey && nvalue != nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def initialize(k, v)
|
34
|
+
@key, @value = k, v
|
35
|
+
end
|
36
|
+
|
37
|
+
def normalize
|
38
|
+
# NOTE: [xxx, nil] is not set to @config
|
39
|
+
# TODO : [k, v] should be equal to {k ,v}
|
40
|
+
v = @value
|
41
|
+
case @key.to_s
|
42
|
+
when 'host' then
|
43
|
+
['host', if is_yaml_undef?(v) then nil else v end]
|
44
|
+
when 'port' then
|
45
|
+
# {:port => '9887'} is {'port' => 9887}
|
46
|
+
['port', if is_yaml_undef?(v) then nil else v.to_i end]
|
47
|
+
when 'app', 'application', 'name', 'register' then
|
48
|
+
['app', if is_yaml_undef?(v) then nil else v end]
|
49
|
+
when 'class', 'add_class', 'classes' then
|
50
|
+
# {:class => 'cls'} and {'add_class' => {'cls' => nil}} are {'class' => ['cls', nil]}
|
51
|
+
['class', extract_classes(v)]
|
52
|
+
when 'title' then
|
53
|
+
['title', if is_yaml_undef?(v) then nil else v end]
|
54
|
+
when 'text', 'body', 'msg' then
|
55
|
+
['text', if is_yaml_undef?(v) then nil else v end]
|
56
|
+
when 'timeout', 'duration', 'sec' then
|
57
|
+
['timeout', if is_yaml_undef?(v) then 0 else v.to_i end] # "timeout: nil" is sticky
|
58
|
+
when 'sticky' then
|
59
|
+
['timeout', if is_yaml_false?(v) then nil else 0 end]
|
60
|
+
when 'icon' then # NOTE: is "this notification icon", not "iconset setting"
|
61
|
+
['icon', if is_yaml_undef?(v) then nil else v end]
|
62
|
+
when 'notification', 'notify', 'message' then
|
63
|
+
['notification', if is_yaml_undef?(v) then nil else v end]
|
64
|
+
when 'unregister' then
|
65
|
+
['unregister', if is_yaml_false?(v) then false else true end]
|
66
|
+
when 'iconset' then
|
67
|
+
['iconset', if is_yaml_undef?(v) then nil else v end]
|
68
|
+
|
69
|
+
when 'log', 'logger' then # useless on yaml?
|
70
|
+
['logger', v]
|
71
|
+
when 'logfile' then
|
72
|
+
['logfile', extract_logfile(v)]
|
73
|
+
when 'loglevel', 'logger.level', 'log_level' then
|
74
|
+
['loglevel', extract_loglevel(v)]
|
75
|
+
|
76
|
+
when 'config' then
|
77
|
+
['config', if is_yaml_undef?(v) then nil else v end]
|
78
|
+
when 'yaml' then
|
79
|
+
['yaml', if is_yaml_undef?(v) then nil else v end]
|
80
|
+
|
81
|
+
else [@key.to_s, v] # or raise?
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def is_yaml_undef?(v)
|
88
|
+
v == 'nil' || v == nil || v == ':nil' || v == :nil || v == '' || v == [] || v == {}
|
89
|
+
end
|
90
|
+
def is_yaml_false?(v)
|
91
|
+
is_yaml_undef?(v) || v == false || v == 'false' || v == :false || v == ':false'
|
92
|
+
end
|
93
|
+
|
94
|
+
def extract_classes(v)
|
95
|
+
if v.kind_of?(Array) then
|
96
|
+
res = []
|
97
|
+
v.each do |a|
|
98
|
+
pair = [a].flatten
|
99
|
+
pair.push(nil) if pair.size == 1
|
100
|
+
res << pair
|
101
|
+
end
|
102
|
+
return res
|
103
|
+
elsif v.kind_of?(String)
|
104
|
+
return [[v, nil]]
|
105
|
+
else
|
106
|
+
return nil
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
def extract_logfile(v)
|
111
|
+
if is_yaml_undef?(v) then nil else {'$stdout' => $stdout, '$stderr' => $stderr}[v.to_s] || v end
|
112
|
+
end
|
25
113
|
|
26
|
-
|
27
|
-
|
28
|
-
|
114
|
+
def extract_loglevel(v)
|
115
|
+
if is_yaml_undef?(v) then
|
116
|
+
return 0
|
117
|
+
else
|
118
|
+
return /\d/ =~ v.to_s ? v.to_s.to_i : (%w(DEBUG INFO WARN ERROR FATAL).index(v.to_s.upcase) || 0)
|
119
|
+
end
|
120
|
+
end
|
29
121
|
end
|
30
122
|
end
|
31
123
|
end
|
data/lib/snarl/snp/error.rb
CHANGED
@@ -16,6 +16,9 @@ class Snarl
|
|
16
16
|
class SNP_OK < Casual ; end
|
17
17
|
# (0) OK
|
18
18
|
|
19
|
+
class SNP_ERROR_NOT_RUNNING < Casual ; end
|
20
|
+
# (201) Incoming network notification handling has been disabled by the user.
|
21
|
+
|
19
22
|
class SNP_ERROR_NOT_REGISTERED < Casual ; end
|
20
23
|
# (202) The application hasn't been registered.
|
21
24
|
|
@@ -25,11 +28,12 @@ class Snarl
|
|
25
28
|
class SNP_ERROR_CLASS_ALREADY_EXISTS < Casual ; end
|
26
29
|
# (204) Class is already registered.
|
27
30
|
|
28
|
-
|
29
|
-
|
30
|
-
class SNP_ERROR_FAILED < Fatal ; end
|
31
|
+
# "Do not Disturb" often raises this error...
|
32
|
+
class SNP_ERROR_FAILED < Casual ; end #Fatal ; end
|
31
33
|
# (101) An internal error occurred - usually this represents a fault within Snarl itself.
|
32
34
|
|
35
|
+
class Fatal < SNPError ; end
|
36
|
+
|
33
37
|
class SNP_ERROR_UNKNOWN_COMMAND < Fatal ; end
|
34
38
|
# (102) An unknown action was specified.
|
35
39
|
|
@@ -39,9 +43,6 @@ class Snarl
|
|
39
43
|
class SNP_ERROR_BAD_PACKET < Fatal ; end
|
40
44
|
# (107) The command packet is wrongly formed.
|
41
45
|
|
42
|
-
class SNP_ERROR_NOT_RUNNING < Fatal ; end
|
43
|
-
# (201) Incoming network notification handling has been disabled by the user.
|
44
|
-
|
45
46
|
class RUBYSNARL_UNKNOWN_RESPONSE < Fatal ; end
|
46
47
|
# (???) Snarl returns unknown return code.
|
47
48
|
|
data/lib/snarl/snp/request.rb
CHANGED
@@ -23,60 +23,70 @@ class Snarl
|
|
23
23
|
# make SNP request string from command hash and is Request object.
|
24
24
|
def initialize(cmd_hash={})
|
25
25
|
@commands = {}.update(cmd_hash)
|
26
|
+
normalize unless @commands.empty?
|
26
27
|
end
|
27
28
|
|
28
29
|
attr_reader :commands
|
29
30
|
|
30
31
|
# Adds command key and value to Request
|
31
|
-
def []=(cmdkey, value)
|
32
|
+
def []=(cmdkey, value)
|
33
|
+
norm_cmdkey = normalize_cmdkey(cmdkey)
|
34
|
+
if norm_cmdkey == 'action' then
|
35
|
+
@commands['action'] = normalize_action_value(value)
|
36
|
+
else
|
37
|
+
@commands[norm_cmdkey] = normalize_value(value)
|
38
|
+
end
|
39
|
+
end
|
32
40
|
# Returns command value for command key
|
33
|
-
def [](cmdkey)
|
41
|
+
def [](cmdkey) ; @commands[cmdkey] ; end
|
34
42
|
|
35
43
|
# Returns Request query string with SNP_TERMINAL_STRING "\r\n"
|
36
44
|
def to_str ; query + SNP_TERMINAL_STRING ; end # FIXME: include "\r\n"?
|
37
45
|
alias :to_s :to_str
|
38
46
|
# Returns Request query string. has no SNP_TERMINAL_STRING "\r\n".
|
39
|
-
def inspect ; query ; end
|
47
|
+
def inspect ; query.inspect ; end
|
40
48
|
def action ; @commands['action'] ; end
|
41
49
|
|
42
50
|
private
|
43
51
|
|
44
|
-
def
|
45
|
-
action = @commands['action']
|
52
|
+
def align_command_pair
|
46
53
|
@commands.to_a.sort_by{|pair| SNP_ACTIONS[action].index(pair[0])}
|
47
54
|
end
|
48
55
|
|
49
56
|
def query
|
50
|
-
|
51
|
-
|
57
|
+
# @commands is already normalized
|
58
|
+
align_command_pair.map{|pair| pair.join('=')}.join(SNP_SEPARATOR)
|
52
59
|
end
|
53
60
|
|
54
|
-
# normalize item pairs
|
61
|
+
# normalize command item pairs {cmdkey => value}
|
55
62
|
# - symbol keys and upcase KEYS are normalized into downcased string keys.
|
56
|
-
# -
|
57
|
-
# -
|
63
|
+
# - value should not have any "\r". use one "\n" as a newline.
|
64
|
+
# - {'action' => 'add-class' or :add_class} are {'action' => 'add_class'}.
|
65
|
+
# - when value is nil, delete the pair.
|
58
66
|
def normalize
|
59
|
-
|
60
|
-
action = normalize_action(norm_commands['action'])
|
61
|
-
norm_commands['action'] = action
|
67
|
+
unnormalized_commands = @commands.dup
|
62
68
|
@commands = SNP_HEADER.dup
|
63
|
-
|
64
|
-
|
65
|
-
|
69
|
+
unnormalized_commands.each{|cmdkey, value| self[cmdkey] = value}
|
70
|
+
available_commands = SNP_ACTIONS[self.action] || [] # or raise
|
71
|
+
@commands.delete_if{|cmdkey, value| !available_commands.include?(cmdkey)}
|
72
|
+
@commands.delete_if{|cmdkey, value| value.nil?} # || value.empty? # TODO: "timeout=" is vaild SNP?
|
73
|
+
@commands
|
66
74
|
end
|
67
75
|
|
68
|
-
def
|
69
|
-
|
76
|
+
def normalize_cmdkey(cmdkey)
|
77
|
+
crlf2lf(cmdkey).downcase
|
70
78
|
end
|
71
|
-
|
72
|
-
|
73
|
-
SNP_ACTIONS[action] || {}
|
79
|
+
def normalize_value(value)
|
80
|
+
crlf2lf(value)
|
74
81
|
end
|
75
82
|
|
76
83
|
def crlf2lf(s)
|
77
84
|
s ? s.to_s.gsub(/\r\n/){"\n"}.gsub(/\r/){"\n"} : s
|
78
85
|
end
|
79
86
|
|
87
|
+
def normalize_action_value(value)
|
88
|
+
normalize_value(value).downcase.gsub(/-/){'_'}.sub(/\Aaddclass\Z/){'add_class'}
|
89
|
+
end
|
80
90
|
end
|
81
91
|
end
|
82
92
|
end
|
data/lib/snarl/snp/response.rb
CHANGED
data/lib/snarl/snp/snp.rb
CHANGED
@@ -3,6 +3,7 @@ class Snarl # conpat for ruby-snarl
|
|
3
3
|
class SNP
|
4
4
|
|
5
5
|
include Action
|
6
|
+
include SNPProcedure
|
6
7
|
|
7
8
|
# default "timeout command" value. popup disappers in 10 seconds.
|
8
9
|
DEFAULT_TIMEOUT = 10
|
@@ -11,49 +12,60 @@ class Snarl # conpat for ruby-snarl
|
|
11
12
|
DEFAULT_TITLE = 'Ruby-Snarl'
|
12
13
|
|
13
14
|
# Snarl::SNP.new('127.0.0.1', 9887)
|
14
|
-
def initialize(host=nil, port=nil, verbose=false)
|
15
|
-
@
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
15
|
+
def initialize(host=nil, port=nil, verbose=false, &block)
|
16
|
+
@config = Config.new
|
17
|
+
if host && YAML.load(host).kind_of?(Hash) then
|
18
|
+
port.respond_to?(:debug) ? load(host, port, &block) : load(host, nil, &block)
|
19
|
+
else
|
20
|
+
self['host'] = host
|
21
|
+
self['port'] = port
|
22
|
+
self['verbose'] = verbose
|
23
|
+
yield(self) if block_given?
|
24
|
+
end
|
23
25
|
end
|
26
|
+
attr_reader :config
|
27
|
+
|
28
|
+
def []=(k, v) ; @config[k] =v ; end
|
29
|
+
def [](k) ; @config[k] ; end
|
24
30
|
|
25
31
|
# When you set it true, all unimportant SNP errors raise.
|
26
32
|
# Default is false, Snarl::SNP::Error::Casual are disabled.
|
27
|
-
|
28
|
-
|
29
|
-
# a value of SNP command "app".
|
30
|
-
attr_reader :app
|
33
|
+
def verbose=(v) ; self['verbose'] = v ; end
|
34
|
+
def verbose ; self['verbose'] ; end
|
31
35
|
|
32
|
-
|
36
|
+
# # a value of SNP command "app".
|
37
|
+
# attr_reader :app
|
38
|
+
#
|
39
|
+
# attr_accessor :title
|
33
40
|
|
34
|
-
# a value of SNP command "timeout".
|
35
|
-
attr_accessor :timeout
|
41
|
+
# # a value of SNP command "timeout".
|
42
|
+
# attr_accessor :timeout
|
36
43
|
|
37
44
|
# set Logger object. It is used when sending request and getting response.
|
38
45
|
def logger=(logger)
|
39
|
-
|
46
|
+
self['logger'] = (logger.kind_of?(Class) ? logger.new($stdout) : logger)
|
40
47
|
end
|
48
|
+
def logger ; self['logger'] ; end
|
41
49
|
|
42
50
|
# send Snarl::SNP::Request/Hash/String and get Snarl::SNP::Response fron Snarl.
|
43
51
|
# When the response "fatal" response, raise errors.
|
44
52
|
# When method +verbose+ returns true, "casual" errors also raises.
|
45
53
|
def request(req)
|
46
54
|
req = Request.new(req) if req.kind_of?(Hash)
|
47
|
-
|
55
|
+
action = if req.kind_of?(Request) then req.action else '(string)' end
|
56
|
+
debug("#{action}: #{req.inspect}")
|
48
57
|
begin
|
49
|
-
action = req.kind_of?(Request) ? req.action : '(string)'
|
50
58
|
res = get_response(req)
|
51
59
|
info("#{action}: #{res.inspect}")
|
52
60
|
rescue Error::Casual => ex
|
53
61
|
info("#{action}: (ignored) #{ex.message}")
|
54
62
|
raise if verbose
|
63
|
+
res = ex.response
|
55
64
|
rescue Error::Fatal => ex
|
56
|
-
|
65
|
+
error("#{action}: #{ex.message}")
|
66
|
+
raise
|
67
|
+
rescue Errno::ECONNREFUSED => ex
|
68
|
+
error("#{ex.message} / #{self['host'].inspect}:#{self['port'].inspect}")
|
57
69
|
raise
|
58
70
|
end
|
59
71
|
return res
|
@@ -63,25 +75,22 @@ class Snarl # conpat for ruby-snarl
|
|
63
75
|
|
64
76
|
# add_classes('type1', 'type2', 'type3')
|
65
77
|
# add_classes(['type1', desc1], ['type2', desc2], ['type3', desc3])
|
78
|
+
# add_classes(*array_of_pairs)
|
79
|
+
# returns [add_class_response1, add_class_response2, add_class_response3]
|
66
80
|
def add_classes(*classes)
|
67
|
-
classes.
|
68
|
-
classpair = [classpair, nil] if classpair.kind_of?(String)
|
69
|
-
add_class(*classpair)
|
70
|
-
end
|
81
|
+
classes.map{|e| e.kind_of?(String) ? [e, nil] : e}.map{|p| add_class(*p)}
|
71
82
|
end
|
72
83
|
|
73
84
|
# returns icon path if SNP knows. optional.
|
74
85
|
def icon(s)
|
75
|
-
if
|
86
|
+
if self['iconset'] && self['iconset'].has_key?(s) then self['iconset'][s] else s end
|
76
87
|
end
|
77
88
|
|
78
89
|
# set icons pair. quite optional.
|
79
|
-
# snp.iconset(:red => 'red.jpg')
|
90
|
+
# snp.iconset({:red => 'red.jpg'})
|
80
91
|
# snp.notification('title', 'text', :red) #=> sends "icon=red.jpg"
|
81
92
|
# snp.notification('title', 'text', 'blue') #=> sends "icon=blue"
|
82
|
-
def iconset(icons)
|
83
|
-
@iconset = icons
|
84
|
-
end
|
93
|
+
def iconset(icons) ; self['iconset'] = icons ; end
|
85
94
|
alias :icons :iconset
|
86
95
|
|
87
96
|
def ping
|
@@ -106,9 +115,11 @@ class Snarl # conpat for ruby-snarl
|
|
106
115
|
client
|
107
116
|
end
|
108
117
|
|
109
|
-
# send message only. app is "anonymous".
|
110
|
-
# Snarl::SNP.show_message(host, 9887, title, text,
|
111
|
-
# Snarl::SNP.show_message(host, title, text,
|
118
|
+
# send message only. app and class is "anonymous".
|
119
|
+
# Snarl::SNP.show_message(host, 9887, title, text, timeout, icon)
|
120
|
+
# Snarl::SNP.show_message(host, title, text, timeout, icon)
|
121
|
+
# Snarl::SNP.show_message(host, title, text)
|
122
|
+
# Snarl::SNP.show_message(host, text)
|
112
123
|
def self.show_message(host, port, title=nil, text=nil, timeout=nil, icon=nil)
|
113
124
|
# TODO: (host, title, text, 10)
|
114
125
|
if port.kind_of?(String) && icon.nil? then
|
@@ -124,19 +135,23 @@ class Snarl # conpat for ruby-snarl
|
|
124
135
|
|
125
136
|
private
|
126
137
|
|
127
|
-
def
|
128
|
-
|
129
|
-
|
130
|
-
TCPSocket.open(host, port) do |s|
|
138
|
+
def send(req)
|
139
|
+
# normalize just before using # FIXME:
|
140
|
+
TCPSocket.open(self['host'], self['port']) do |s|
|
131
141
|
s.write(req)
|
132
|
-
|
133
|
-
res.request = req
|
134
|
-
res
|
142
|
+
s.gets
|
135
143
|
end
|
136
144
|
end
|
137
145
|
|
138
|
-
def
|
139
|
-
|
146
|
+
def get_response(req)
|
147
|
+
res = Response.new(send(req))
|
148
|
+
res.request = req
|
149
|
+
res
|
150
|
+
end
|
151
|
+
|
152
|
+
def error(m); logger.error(m) if logger ; end
|
153
|
+
def info(m); logger.info(m) if logger ; end
|
154
|
+
def debug(m); logger.debug(m) if logger ; end
|
140
155
|
|
141
156
|
end
|
142
157
|
end
|