sleipnir-api 0.2.1 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/History.txt +32 -0
  2. data/Manifest.txt +20 -3
  3. data/Rakefile +11 -1
  4. data/TODO.txt +4 -10
  5. data/bin/grepnir +1 -1
  6. data/examples/close_dup.rb +1 -1
  7. data/examples/close_err.rb +12 -0
  8. data/examples/command_list.rb +135 -0
  9. data/examples/open_last_url_by_firefox.rb +44 -0
  10. data/examples/open_selected_links.rb +40 -0
  11. data/helper/rake.rb +3 -57
  12. data/helper/rake/rake.rb +58 -0
  13. data/helper/{rake_sh_filter.rb → rake/rake_sh_filter.rb} +0 -0
  14. data/helper/{util.rb → rake/util.rb} +0 -0
  15. data/lib/sleipnir_api/cli/grepnir.rb +2 -3
  16. data/lib/sleipnir_api/command.rb +126 -0
  17. data/lib/sleipnir_api/commands.rb +264 -0
  18. data/lib/sleipnir_api/profile.rb +166 -27
  19. data/lib/sleipnir_api/profile/ini.rb +202 -0
  20. data/lib/sleipnir_api/profile/key.rb +120 -0
  21. data/lib/sleipnir_api/profile/section.rb +147 -0
  22. data/lib/sleipnir_api/profile/util.rb +82 -0
  23. data/lib/sleipnir_api/searcher.rb +133 -0
  24. data/lib/sleipnir_api/security.rb +88 -18
  25. data/lib/sleipnir_api/sleipnir.rb +91 -7
  26. data/lib/sleipnir_api/tab.rb +68 -2
  27. data/lib/sleipnir_api/tabbed_ie.rb +33 -0
  28. data/lib/sleipnir_api/util.rb +25 -0
  29. data/lib/sleipnir_api/version.rb +2 -2
  30. data/scripts/gesture2rb.rb +42 -0
  31. data/scripts/make_gesture.rb +271 -0
  32. data/scripts/subcategory.csv +253 -0
  33. data/spec/sleipnir_api/profile_mock_spec.rb +80 -6
  34. data/spec/sleipnir_api/profile_section_mock_spec.rb +143 -0
  35. data/spec/sleipnir_api/profile_spec.rb +191 -0
  36. data/spec/sleipnir_api/security_spec.rb +58 -0
  37. data/spec/sleipnir_api/tab_mock_spec.rb +0 -5
  38. data/spec/sleipnir_api/tab_spec.rb +27 -0
  39. data/spec/spec_helper.rb +20 -0
  40. metadata +22 -5
  41. data/helper/helper.rb +0 -3
@@ -0,0 +1,120 @@
1
+ require "sleipnir_api/util"
2
+ require "sleipnir_api/profile/util"
3
+
4
+ module SleipnirAPI
5
+ class Profile
6
+
7
+ # ini ファイルのキーに対応するオブジェクトです。
8
+ # このオブジェクトは SleipnirAPI::Profile::Section#key で取得します。
9
+ #
10
+ # pnir = SleipnirAPI.new
11
+ # ini = pnir.profile("CloseURL.ini")
12
+ # sec = ini.section("ClosedURL2")
13
+ # key = sec.key("URL0")
14
+ # key.to_s #=> "http://hogehoge"
15
+ #
16
+ class Key < ProfileElement
17
+
18
+ # SleipnirAPI::Profile::Section オブジェクトを返します
19
+ attr_reader :parent
20
+
21
+ # SleipnirAPI::Profile::Section オブジェクトを返します
22
+ alias section parent
23
+
24
+ # キー名を返します。
25
+ attr_reader :name
26
+
27
+ # #get_string などに指定するデフォルトの引数を取得します。
28
+ # 値は #parent から引き継いでいます。
29
+ attr_reader :default_opts
30
+
31
+ def initialize(parent, name, default_opts = nil)
32
+ super(parent, default_opts)
33
+ @name = name
34
+ end
35
+
36
+ # call-seq:
37
+ # list(countkey="Count")
38
+ # list(countkey="Count", :default => "default value")
39
+ # list(countkey="Count", :cipher => true)
40
+ # list(countkey="Count", :cipher => true, :default => "default value")
41
+ #
42
+ # このキーから連番キーを生成して、連番データをすべて読み込み配列で返します。
43
+ #
44
+ # 例:
45
+ #
46
+ # pnir = SleipnirAPI.connect
47
+ # proxy_ini = pnir.profile.proxy
48
+ # proxy_sec = proxy_ini.Proxy
49
+ # proxy_title = proxy_sec.Proxy0_Title
50
+ # proxy_title.list
51
+ #
52
+ # See Also: SleipnirAPI::Profile#list
53
+ def list(countkey = "Count", opts = nil, &block)
54
+ @parent.list(@name, countkey, options(opts), &block)
55
+ end
56
+ alias to_a list
57
+
58
+ # call-seq:
59
+ # get_string()
60
+ # get_string(:default => -1)
61
+ # get_string(:cipher => true)
62
+ # get_string(:cipher => true, :default => -1)
63
+ #
64
+ # このキーの string 値を取得します。
65
+ #
66
+ # See Also: SleipnirAPI::Profile#get_string
67
+ def get_string(opts = nil)
68
+ @parent.get_string(@name, options(opts))
69
+ end
70
+ alias to_s get_string
71
+
72
+ # call-seq:
73
+ # get_int()
74
+ # get_int(:default => -1)
75
+ # get_int(:cipher => true)
76
+ # get_int(:cipher => true, :default => -1)
77
+ #
78
+ # このキーの int 値を取得します。
79
+ #
80
+ # See Also: SleipnirAPI::Profile#get_int
81
+ def get_int(opts = nil)
82
+ @parent.get_int(@name, options(opts))
83
+ end
84
+ alias to_i get_int
85
+
86
+ # call-seq:
87
+ # write_string(data)
88
+ # write_string(data, :cipher => true)
89
+ #
90
+ # このキーに指定されたデータを書き込みます。
91
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
92
+ #
93
+ # See Also: SleipnirAPI::Profile#write_string
94
+ def write_string(data, opts = nil)
95
+ @parent.write_string(@name, data, options(opts))
96
+ end
97
+
98
+ # call-seq:
99
+ # write_int(data)
100
+ # write_int(data, :cipher => true)
101
+ #
102
+ # このキーに指定されたデータを書き込みます。
103
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
104
+ #
105
+ # See Also: SleipnirAPI::Profile#write_int
106
+ def write_int(data, opts = nil)
107
+ @parent.write_int(@name, data, options(opts))
108
+ end
109
+
110
+ # このキーを削除します。
111
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
112
+ #
113
+ # See Also: SleipnirAPI::Profile#delete
114
+ def delete
115
+ @parent.delete(name)
116
+ end
117
+
118
+ end
119
+ end
120
+ end
@@ -0,0 +1,147 @@
1
+ require "sleipnir_api/util"
2
+ require "sleipnir_api/profile/util"
3
+
4
+ module SleipnirAPI
5
+ class Profile
6
+
7
+ # ini ファイルのセクションに対応するオブジェクトです。
8
+ # このオブジェクトは SleipnirAPI::Profile::Ini#section で取得します。
9
+ #
10
+ # pnir = SleipnirAPI.new
11
+ # ini = pnir.profile("CloseURL.ini")
12
+ # sec = ini.section("ClosedURL2")
13
+ # sec.get_string("URL0") #=> "http://hogehoge"
14
+ #
15
+ # #key でこのセクション内のキーに対応する SleipnirAPI::Profile::Key
16
+ # オブジェクトを取得できます。
17
+ class Section < ProfileElement
18
+
19
+ # SleipnirAPI::Profile::Ini オブジェクトを返します
20
+ attr_reader :parent
21
+
22
+ # SleipnirAPI::Profile::Ini オブジェクトを返します
23
+ alias ini parent
24
+
25
+ # セクション名を返します。
26
+ attr_reader :name
27
+
28
+ # セクション名を返します。
29
+ alias to_s name
30
+
31
+ # #get_string などに指定するデフォルトの引数を取得します。
32
+ # 値は #parent から引き継いでいます。
33
+ attr_reader :default_opts
34
+
35
+ def initialize(parent, name, default_opts = nil)
36
+ super(parent, default_opts)
37
+ @name = name
38
+ end
39
+
40
+ # call-seq:
41
+ # list(keyfmt, countkey="Count")
42
+ # list(keyfmt, countkey="Count", :default => "default value")
43
+ # list(keyfmt, countkey="Count", :cipher => true)
44
+ # list(keyfmt, countkey="Count", :cipher => true, :default => "default value")
45
+ #
46
+ # このセクションから連番キーのデータをすべて読み込み配列で返します。
47
+ #
48
+ # 例:
49
+ #
50
+ # pnir = SleipnirAPI.connect
51
+ # proxy_ini = pnir.profile.proxy
52
+ # proxy_sec = proxy_ini.Proxy
53
+ # proxy_sec.list("Proxy0_Title")
54
+ #
55
+ # See Also: SleipnirAPI::Profile#list
56
+ def list(keyformat, countkey = "Count", opts = nil, &block)
57
+ @parent.list(@name, keyformat, countkey, options(opts), &block)
58
+ end
59
+
60
+ # call-seq:
61
+ # get_string(key)
62
+ # get_string(key, :default => -1)
63
+ # get_string(key, :cipher => true)
64
+ # get_string(key, :cipher => true, :default => -1)
65
+ #
66
+ # このセクションの指定されたキーを取得します。
67
+ #
68
+ # See Also: SleipnirAPI::Profile#get_string
69
+ def get_string(key, opts = nil)
70
+ @parent.get_string(@name, key, options(opts))
71
+ end
72
+ alias [] get_string
73
+
74
+ # call-seq:
75
+ # get_int(key)
76
+ # get_int(key, :default => -1)
77
+ # get_int(key, :cipher => true)
78
+ # get_int(key, :cipher => true, :default => -1)
79
+ #
80
+ # このセクションの指定されたキーを取得します。
81
+ #
82
+ # See Also: SleipnirAPI::Profile#get_int
83
+ def get_int(key, opts = nil)
84
+ @parent.get_int(@name, key, options(opts))
85
+ end
86
+
87
+ # call-seq:
88
+ # write_string(key, data)
89
+ # write_string(key, data, :cipher => true)
90
+ #
91
+ # このセクションの指定されたキーを書き込みます。
92
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
93
+ #
94
+ # See Also: SleipnirAPI::Profile#write_string
95
+ def write_string(key, data, opts = nil)
96
+ @parent.write_string(@name, key, data, options(opts))
97
+ end
98
+
99
+ # call-seq:
100
+ # write_int(key, data)
101
+ # write_int(key, data, :cipher => true)
102
+ #
103
+ # このセクションの指定されたキーを書き込みます。
104
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
105
+ #
106
+ # See Also: SleipnirAPI::Profile#write_int
107
+ def write_int(key, data, opts = nil)
108
+ @parent.write_int(@name, key, data, options(opts))
109
+ end
110
+
111
+ # このセクションの指定されたキーを削除します。
112
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
113
+ #
114
+ # See Also: SleipnirAPI::Profile#delete
115
+ def delete(key)
116
+ @parent.delete(@name, key)
117
+ end
118
+
119
+ # キーを操作する Sleipnir::Profile::Key オブジェクトを返します。
120
+ #
121
+ # pnir = SleipnirAPI.connect
122
+ # proxy = pnir.profile.ini("Proxy.ini", :default => 123)
123
+ # sec = proxy.section("Proxy")
124
+ # key = sec.key("Count")
125
+ # key.get_int
126
+ #
127
+ # See Also: #method_missing
128
+ def key(name, opts = nil)
129
+ Key.new(self, str(name), options(opts))
130
+ end
131
+
132
+ # メソッド名をキー名とみなして Sleipnir::Profile::Key オブジェクトを返します。
133
+ #
134
+ # pnir = SleipnirAPI.connect
135
+ # proxy = pnir.profile.Proxy(:default => 123)
136
+ # sec = proxy.Proxy
137
+ # key = sec.Count
138
+ # key.get_int
139
+ #
140
+ # See Also: #key
141
+ def method_missing(mid, *args, &block)
142
+ key(mid.to_s, *args, &block)
143
+ end
144
+
145
+ end
146
+ end
147
+ end
@@ -0,0 +1,82 @@
1
+ require "sleipnir_api/util"
2
+
3
+ module SleipnirAPI
4
+ class Profile
5
+ #
6
+ # Script.ini 以外の ini ファイルに対して、書き込み (write_int, write_string, delete)
7
+ # を行った場合に raise する例外
8
+ #
9
+ class ReadOnlyError < StandardError; end
10
+
11
+ module OptionArgument #:nodoc:
12
+ include SleipnirAPI::OptionUtil
13
+
14
+ def options(opts, *valid_keys)
15
+ if opts and not Hash === opts
16
+ raise ArgumentError, "Invalid options: #{opts.inspect}:#{opts.class} (expected Hash)"
17
+ end
18
+ r = @default_opts ? @default_opts.dup : {}
19
+ valid_keys = [:cipher, :ini, :default] if valid_keys.empty?
20
+ if opts
21
+ invalid = (opts.keys - valid_keys).inject({}){|acc,e| acc[e] = opts[e]; acc }
22
+ unless invalid.empty?
23
+ raise ArgumentError, "Invalid options: #{invalid.inspect}"
24
+ end
25
+ r.update(opts)
26
+ end
27
+ r
28
+ end
29
+ end
30
+
31
+ module DataUtil #:nodoc:
32
+ def str(*args)
33
+ args = args.map{|e|
34
+ case e
35
+ when String
36
+ e
37
+ when Symbol
38
+ e.to_s
39
+ else
40
+ raise ArgumentError, "Invalid date #{e.inspect}:#{e.class} (expected String or Symbol)"
41
+ end
42
+ }
43
+ (args.length == 1) ? args[0] : args
44
+ end
45
+
46
+ def check_data(section, key, data, expected)
47
+ unless expected === data
48
+ raise ArgumentError, "Invalid data `#{data.inspect}' (#{data.class}): section=#{section}, key=#{key} (expected #{expected})"
49
+ end
50
+ end
51
+ end
52
+
53
+ class ProfileElement #:nodoc:
54
+ include OptionArgument
55
+ include DataUtil
56
+
57
+ def initialize(parent, default_opts)
58
+ @parent = parent
59
+ @default_opts = default_opts || {}
60
+ end
61
+
62
+ def parents
63
+ @parent.nil? ? [] : @parent.nodes
64
+ end
65
+
66
+ def nodes
67
+ parents + [self]
68
+ end
69
+
70
+ def inspect
71
+ args = [
72
+ self.class,
73
+ object_id << 1,
74
+ nodes.map{|e| e.name }.join("/"),
75
+ @default_opts.inspect,
76
+ ]
77
+ "#<%s:0x%x: %s, opts=%s>" % args
78
+ end
79
+
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,133 @@
1
+ require "sleipnir_api/util"
2
+
3
+ module SleipnirAPI
4
+
5
+ class Searcher #:nodoc:
6
+ include SleipnirAPI::Util
7
+ include SleipnirAPI::OptionUtil
8
+
9
+ HILIGHT_TAG = "span"
10
+ HILIGHT_CLASSNAME = "ruby-sleipnir-api-hilight"
11
+ HILIGHT_STYLE = "color: black; background-color: #ffff66; font-weight: bold"
12
+
13
+ def initialize(tab)
14
+ @tab = tab
15
+ @range = nil
16
+ end
17
+
18
+ def each_find_text(keyword, range = nil)
19
+ range = @tab.document.body.createTextRange
20
+ while range.FindText(keyword)
21
+ yield range
22
+ range.Collapse(false)
23
+ end
24
+ end
25
+
26
+ def find_text(keyword, *options)
27
+ opts, _ = parse_option_arguments(options)
28
+
29
+ if not @range
30
+ @range = @tab.document.body.createTextRange
31
+ else
32
+ @range.Collapse(false)
33
+ end
34
+
35
+ if @range.FindText(keyword)
36
+ @range.Select if opts[:select]
37
+ @range.ScrollIntoView if opts[:scroll]
38
+ true
39
+ else
40
+ @tab.document.Selection.empty if opts[:select]
41
+ @range = nil
42
+ false
43
+ end
44
+ end
45
+
46
+ def hilight(*keywords)
47
+ remove_hilight
48
+ range = @tab.document.body.createTextRange
49
+ matches = []
50
+ keywords.each do |kwd|
51
+ each_find_text(kwd, range) do |range|
52
+ matched_html = range.HTMLText
53
+ matches << matched_html.gsub(/\A(<[^<>]+>)+/, "").gsub(/(<[^<>]+>)+\z/, "")
54
+ end
55
+ range.Collapse(true)
56
+ end
57
+
58
+ all=@tab.document.body.innerHTML
59
+ @tab.document.body.innerHTML = matches.uniq.inject(all) do |all,m|
60
+ add_hilight_tag(m, all)
61
+ end
62
+ end
63
+
64
+ def add_hilight_tag(matched, html=nil, tag=HILIGHT_TAG, classname=HILIGHT_CLASSNAME, style=HILIGHT_STYLE)
65
+ if html.nil?
66
+ "<#{tag} class='#{classname}' style='#{style}'>#{matched}</#{tag}>"
67
+ else
68
+ matched = matched.gsub(/\A(<[^<>]+>)+/, "").gsub(/(<[^<>]+>)+\z/, "")
69
+ html.gsub(/#{Regexp.quote(matched)}/) do
70
+ matched.split(/(<[^<>]+>)/).map{|part|
71
+ if part[0] != ?< and part =~ /\S/
72
+ "<#{tag} class='#{classname}' style='#{style}'>#{part}</#{tag}>"
73
+ else
74
+ part
75
+ end
76
+ }.join
77
+ end
78
+ end
79
+ end
80
+
81
+ def remove_hilight
82
+ @tab.document.body.getElementsByTagName(HILIGHT_TAG).each do |span|
83
+ span.OuterHTML = span.InnerHTML if span.ClassName == HILIGHT_CLASSNAME
84
+ end
85
+ end
86
+
87
+ =begin
88
+ def hilight(*keywords)
89
+ remove_hilight
90
+ range = @tab.document.body.createTextRange
91
+ keywords.each do |kwd|
92
+ each_find_text(kwd, range) do |range|
93
+ matched_html = range.HTMLText
94
+ parent_tags = matched_html[/\A(?:<[^<>]+>)+/]
95
+ if parent_tags.nil?
96
+ range.PasteHTML(add_hilight_tag(matched_html))
97
+ else
98
+ e = parent_tags.scan(/<(\w+)/).flatten.reverse.inject(range.ParentElement) do |elem,tag|
99
+ if elem.TagName == tag
100
+ elem.ParentElement
101
+ elsif elem.InnerHTML =~ /\A<#{tag}/i
102
+ elem
103
+ else
104
+ raise "#{elem}:#{tag}:#{parent_tags.inspect}"
105
+ end
106
+ end
107
+ e.innerHTML = add_hilight_tag(matched_html, e.innerHTML)
108
+ end
109
+ end
110
+ range.Collapse(true)
111
+ end
112
+ end
113
+
114
+ def add_hilight_tag(matched, html=nil, tag=HILIGHT_TAG, classname=HILIGHT_CLASSNAME, style=HILIGHT_STYLE)
115
+ if html.nil?
116
+ "<#{tag} class='#{classname}' style='#{style}'>#{matched}</#{tag}>"
117
+ else
118
+ matched = matched.gsub(/\A(<[^<>]+>)+/, "").gsub(/(<[^<>]+>)+\z/, "")
119
+ html.sub(/#{Regexp.quote(matched)}/) do
120
+ matched.split(/(<[^<>]+>)/).map{|part|
121
+ if part[0] != ?< and part =~ /\S/
122
+ "<#{tag} class='#{classname}' style='#{style}'>#{part}</#{tag}>"
123
+ else
124
+ part
125
+ end
126
+ }.join
127
+ end
128
+ end
129
+ end
130
+ =end
131
+
132
+ end
133
+ end