sleipnir-api 0.2.1 → 0.3.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.
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