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
@@ -1,46 +1,150 @@
1
1
  require "sleipnir_api/util"
2
+ require "sleipnir_api/profile/ini"
3
+ require "sleipnir_api/profile/section"
4
+ require "sleipnir_api/profile/key"
2
5
 
3
6
  module SleipnirAPI
4
7
 
5
8
  #
6
9
  # このクラスは Sleipnir の COM オブジェクト (Sleipnir.API) の wrapper クラスです。
7
- # Sleipnir の ini ファイルを操作する API を定義しています。
10
+ # Sleipnir の ini ファイルを操作する低レベルな API を定義しています。
11
+ #
12
+ # ini ファイル・セクション・キーに対応するオブジェクトを用意してあるので
13
+ # 通常はそちらを利用してください。
14
+ #
15
+ # * SleipnirAPI::Profile::Ini
16
+ # * SleipnirAPI::Profile::Section
17
+ # * SleipnirAPI::Profile::Key
8
18
  #
9
19
  # このオブジェクトは SleipnirAPI::Sleipnir#profile で取得します。
10
20
  #
11
- # 例:
21
+ # === 高レベル API の例
22
+ #
23
+ # pnir = SleipnirAPI.new
24
+ # prof = pnir.profile
25
+ #
26
+ # # デフォルト値
27
+ # bar = prof.script.foo_section.bar_key
28
+ # # 以下と同じ
29
+ # # bar = prof.ini("Script.ini").section("foo_section").key("bar_key")
30
+ #
31
+ # bar.write_string("foobar")
32
+ # bar.get_string #=> "foobar"
33
+ # bar.delete
34
+ # bar.get_string(:default => "default value") #=> "default value"
35
+ #
36
+ # # 暗号化
37
+ # bar_cipher = prof.script.foo_section.bar_key(:cipher => true)
38
+ # bar_cipher.write_string("foobar")
39
+ # bar_cipher.get_string #=> "foobar"
40
+ # bar.get_string #=> "tibv&DmD[vq)"
41
+ # bar_cipher.get_string(:cipher => false) #=> "tibv&DmD[vq)"
42
+ #
43
+ # # 連番データの取得
44
+ # history = prof.History.History2.key("URL-data0").list("URLCount")
45
+ #
46
+ # === 低レベル API の例
12
47
  #
13
48
  # pnir = SleipnirAPI.new
14
- # ini = pnir.profile
49
+ # prof = pnir.profile
15
50
  #
16
51
  # # デフォルト値
17
- # ini.write_string("section", "key", "foobar")
18
- # ini.get_string("section", "key") #=> "foobar"
19
- # ini.delete("section", "key")
20
- # ini.get_string("section", "key", :default => "default value") #=> "default value"
52
+ # prof.write_string("section_foo", key_bar, "foobar")
53
+ # prof.get_string("section_foo", key_bar) #=> "foobar"
54
+ # prof.delete("section_foo", key_bar)
55
+ # prof.get_string("section_foo", key_bar, :default => "default value") #=> "default value"
21
56
  #
22
57
  # # 暗号化
23
- # ini.write_string("section", "key", "foobar", :cipher => true)
24
- # ini.get_string("section", "key") #=> "tF4DxDH)[uUu"
25
- # ini.get_string("section", "key", :cipher => true) #=> "foobar"
58
+ # prof.write_string("section_foo", key_bar, "foobar", :cipher => true)
59
+ # prof.get_string("section_foo", key_bar, :cipher => true) #=> "foobar"
60
+ # prof.get_string("section_foo", key_bar) #=> "tF4DxDH)[uUu"
26
61
  #
27
- # # ファイル名指定
28
- # count = ini.get_int("Proxy", "Count", :ini => "proxy.ini")
29
- # (0...count).each do |i|
30
- # p ini.get_string("Proxy", "Proxy#{i}_Title", :ini => "proxy.ini")
31
- # end
62
+ # # 連番データの取得
63
+ # history = prof.list("History2", "URL-data0", "URLCount", :ini => "History.ini")
32
64
  #
33
65
  class Profile
34
66
  include SleipnirAPI::Util
67
+ include OptionArgument
68
+ include DataUtil
35
69
 
36
70
  # SleipnirAPI::Sleipnir object
37
- attr_reader :sleipnir
71
+ attr_reader :sleipnir, :default_opts
38
72
 
39
- def initialize(sleipnir)
73
+ def initialize(sleipnir, default_opts = nil)
40
74
  @sleipnir = sleipnir
75
+ @user_path = sleipnir.user_path
76
+ @default_opts = default_opts
41
77
  end
42
78
 
79
+
80
+ # call-seq:
81
+ # list(section, keyfmt, countkey="Count")
82
+ # list(section, keyfmt, countkey="Count", :default => "default value")
83
+ # list(section, keyfmt, countkey="Count", :cipher => true)
84
+ # list(section, keyfmt, countkey="Count", :cipher => true, :default => "default value")
85
+ # list(section, keyfmt, countkey="Count", :ini => ini_filename)
86
+ # list(section, keyfmt, countkey="Count", :ini => ini_filename, :default => "default value")
87
+ #
88
+ # 以下のような連番キーのデータをすべて読み込み配列で返します。
89
+ #
90
+ # [History2]
91
+ # SearchCount=2
92
+ # Search-data0="Ruby"
93
+ # Search-data1="Sleipnir"
94
+ #
95
+ # * +keyfmt+ には連番キーを生成するためのテンプレート文字列を指定します。
96
+ # テンプレート文字列からフォーマット文字列への変換ルールは #list_key_format を参照してください。
97
+ # * +countkey+ には連番キーの個数を記録しているキー名を指定します。
98
+ # デフォルトは "Count" です。
99
+ # * +opts+ の説明は #get_string を参照してください。
100
+ # * +block+ を指定するとフォーマットされた連番キー(文字列)を引数に block を評価して
101
+ # その結果を返します。
102
+ #
103
+ # 例:
104
+ #
105
+ # pnir = SleipnirAPI.connect
106
+ # prof = pnir.profile
107
+ # prof.list("History2", "Search-data0", "SearchCount", :ini => "History.ini") #=> ["Ruby", "Sleipnir"]
108
+ #
109
+ # See Also: #list_key_format
110
+ def list(section, keyfmt, countkey="Count", opts = nil, &block)
111
+ keyfmt = list_key_format(keyfmt)
112
+ block ||= lambda {|key| get_string(section, key, opts) }
113
+ (0...get_int(section, countkey, opts)).map{|i| keyfmt % i }.map(&block)
114
+ end
115
+
116
+ # 連番キーを生成するためのフォーマット文字列を返します。
117
+ #
118
+ # フォーマット文字列は以下のルールで生成します。
43
119
  #
120
+ # * 引数に「%(数字)d」が含まれていればそのまま返す。
121
+ # * 引数に連続する 0 があれば、そこを連番箇所と判断して %d に変換して返す。
122
+ # * 0 が複数箇所に存在する場合は最後の 0 が利用される
123
+ # * 連続する 0 の場合、幅指定のフォーマットになる
124
+ # * 0 が存在しない場合は、以下の場所を連番箇所と判断して %d に変換して返す。
125
+ # * 最初のアンダースコアの前
126
+ # * 文字列末尾
127
+ #
128
+ # 例:
129
+ #
130
+ # list_key_format("Search-data%d") #=> Search-data%d
131
+ #
132
+ # list_key_format("Foo_Bar0_Name") #=> Foo_Bar%d_Name
133
+ # list_key_format("Foo0_Bar0_Name") #=> Foo0_Bar%d_Name
134
+ # list_key_format("Foo0_Bar000_Name") #=> Foo0_Bar%03d_Name
135
+ #
136
+ # list_key_format("Foo_Bar_Name") #=> Foo%d_Bar_Name
137
+ # list_key_format("Name") #=> Name%d
138
+ #
139
+ def list_key_format(keyfmt)
140
+ return keyfmt if keyfmt =~ /%\d*d/
141
+ return keyfmt if keyfmt.sub!(/(0+)(\D*)\z/) {
142
+ n = $1.length
143
+ (n == 1) ? "%d#{$2}" : "%0#{n}d#{$2}"
144
+ }
145
+ return keyfmt.sub(/(_|\z)/) { "%d#{$1}" }
146
+ end
147
+
44
148
  # call-seq:
45
149
  # get_string(section, key)
46
150
  # get_string(section, key, :default => "default value")
@@ -61,7 +165,8 @@ module SleipnirAPI
61
165
  # 同時に指定した場合 <tt>:cipher</tt> は無視されます。
62
166
  #
63
167
  def get_string(section, key, opts = nil)
64
- opts ||= {}
168
+ section, key = str(section, key)
169
+ opts = options(opts, :cipher, :ini, :default)
65
170
  if opts[:ini]
66
171
  api.GetProfileStringEx(section, key, opts[:default], expand_user_path(opts[:ini]))
67
172
  elsif opts[:cipher]
@@ -71,7 +176,6 @@ module SleipnirAPI
71
176
  end
72
177
  end
73
178
 
74
- #
75
179
  # call-seq:
76
180
  # get_int(section, key)
77
181
  # get_int(section, key, :default => -1)
@@ -84,7 +188,8 @@ module SleipnirAPI
84
188
  # 詳細は get_string を参照してください。
85
189
  #
86
190
  def get_int(section, key, opts = nil)
87
- opts ||= {}
191
+ section, key = str(section, key)
192
+ opts = options(opts, :cipher, :ini, :default)
88
193
  if opts[:ini]
89
194
  api.GetProfileIntEx(section, key, opts[:default], expand_user_path(opts[:ini]))
90
195
  elsif opts[:cipher]
@@ -94,7 +199,6 @@ module SleipnirAPI
94
199
  end
95
200
  end
96
201
 
97
- #
98
202
  # call-seq:
99
203
  # write_string(section, key, data)
100
204
  # write_string(section, key, data, :cipher => true)
@@ -104,7 +208,9 @@ module SleipnirAPI
104
208
  # * <tt>:cipher</tt> に true を指定すると暗号化してデータを書き込みます。
105
209
  #
106
210
  def write_string(section, key, data, opts = nil)
107
- opts ||= {}
211
+ section, key = str(section, key)
212
+ check_data(section, key, data, String)
213
+ opts = options(opts, :cipher)
108
214
  if opts[:cipher]
109
215
  api.WriteProfileStringCipher(section, key, data)
110
216
  else
@@ -112,7 +218,6 @@ module SleipnirAPI
112
218
  end
113
219
  end
114
220
 
115
- #
116
221
  # call-seq:
117
222
  # write_int(section, key, data)
118
223
  # write_int(section, key, data, :cipher => true)
@@ -122,7 +227,9 @@ module SleipnirAPI
122
227
  # * <tt>:cipher</tt> に true を指定すると暗号化してデータを書き込みます。
123
228
  #
124
229
  def write_int(section, key, data, opts = nil)
125
- opts ||= {}
230
+ section, key = str(section, key)
231
+ check_data(section, key, data, Integer)
232
+ opts = options(opts, :cipher)
126
233
  if opts[:cipher]
127
234
  api.WriteProfileIntCipher(section, key, data)
128
235
  else
@@ -132,19 +239,51 @@ module SleipnirAPI
132
239
 
133
240
  # <ini_dir>\script.ini から指定されたキーを削除します。
134
241
  def delete(section, key)
242
+ section, key = str(section, key)
135
243
  api.DeleteProfileKey(section, key)
136
244
  end
137
245
 
138
- # <ini_dir> から expand_path します。
246
+ # SleipnirAPI::Sleipnir#user_path から expand_path します。
247
+ #
248
+ # * 引数は to_s で文字列に変換されます。
249
+ # * 拡張子がなければ .ini を付与します。
250
+ #
139
251
  def expand_user_path(ini)
140
- File.expand_path(ini, sleipnir.user_path)
252
+ raise ArgumentError, "Invalid ini file name: #{ini.inspect}" if ini.nil? or ini == ""
253
+ ini = ini.to_s
254
+ if File.extname(ini) == ""
255
+ ini = File.basename(ini, ".*") + ".ini"
256
+ end
257
+ File.expand_path(ini, @user_path)
141
258
  end
142
259
 
143
260
  # <ini_dir>\script.ini のパスを返します。
144
- def script_ini
261
+ def script_ini_path
145
262
  expand_user_path("script.ini")
146
263
  end
147
264
 
265
+ # 指定された ini ファイルを操作する Sleipnir::Profile::Ini オブジェクトを返します。
266
+ #
267
+ # pnir = SleipnirAPI.connect
268
+ # proxy = pnir.profile.ini("Proxy.ini", :default => 123)
269
+ # proxy.get_int("Proxy", "Count")
270
+ #
271
+ # See Also: #method_missing
272
+ def ini(name, opts = nil)
273
+ Ini.new(self, str(name), options(opts))
274
+ end
275
+
276
+ # メソッド名を ini ファイル名とみなして Sleipnir::Profile::Ini オブジェクトを返します。
277
+ #
278
+ # pnir = SleipnirAPI.connect
279
+ # proxy = pnir.profile.Proxy(:default => 123)
280
+ # proxy.get_int("Proxy", "Count")
281
+ #
282
+ # See Also: #ini
283
+ def method_missing(mid, *args, &block)
284
+ ini(mid.to_s, *args, &block)
285
+ end
286
+
148
287
  end
149
288
  end
150
289
 
@@ -0,0 +1,202 @@
1
+ require "sleipnir_api/util"
2
+ require "sleipnir_api/profile/util"
3
+
4
+ module SleipnirAPI
5
+ class Profile
6
+
7
+ # ini ファイルに対応するオブジェクトです。
8
+ # このオブジェクトは SleipnirAPI::Sleipnir#profile で
9
+ # または SleipnirAPI::Profile#ini で取得します。
10
+ #
11
+ # pnir = SleipnirAPI.new
12
+ # ini = pnir.profile("CloseURL.ini")
13
+ # ini.get_string("ClosedURL2", "URL0") #=> "http://hogehoge"
14
+ #
15
+ # #section でこの ini ファイル内のセクションに対応する SleipnirAPI::Profile::Section
16
+ # オブジェクトを取得できます。
17
+ class Ini < ProfileElement
18
+
19
+ # SleipnirAPI::Profile オブジェクトを返します。
20
+ attr_reader :profile
21
+
22
+ # ini ファイル名を返します。
23
+ # これは、SleipnirAPI::Profile#ini に指定した値をそのまま返します。
24
+ # フルパスを得たい場合は #path を利用してください。
25
+ attr_reader :name
26
+
27
+ # #get_string などに指定するデフォルトの引数を取得します。
28
+ # 値は #profile から引き継いでいます。
29
+ attr_reader :default_opts
30
+
31
+ def initialize(profile, name, default_opts = nil)
32
+ super(nil, default_opts)
33
+ @profile = profile
34
+ @name = (name == "" ? nil : name)
35
+ end
36
+
37
+ # call-seq:
38
+ # list(section, keyfmt, countkey="Count")
39
+ # list(section, keyfmt, countkey="Count", :default => "default value")
40
+ # list(section, keyfmt, countkey="Count", :cipher => true)
41
+ # list(section, keyfmt, countkey="Count", :cipher => true, :default => "default value")
42
+ #
43
+ # この ini ファイルから連番キーのデータをすべて読み込み配列で返します。
44
+ #
45
+ # 例:
46
+ #
47
+ # pnir = SleipnirAPI.connect
48
+ # proxy_ini = pnir.profile.proxy
49
+ # proxy_ini.list("Proxy", "Proxy0_Title")
50
+ #
51
+ # See Also: SleipnirAPI::Profile#list
52
+ def list(section, keyfmt, countkey="Count", opts = nil, &block)
53
+ @profile.list(section, keyfmt, countkey, get_options(opts), &block)
54
+ end
55
+
56
+ # call-seq:
57
+ # get_string(section, key)
58
+ # get_string(section, key, :default => "default value")
59
+ # get_string(section, key, :cipher => true)
60
+ # get_string(section, key, :cipher => true, :default => "default value")
61
+ #
62
+ # この ini ファイルから string 型データを読み込みます。
63
+ #
64
+ # See Also: SleipnirAPI::Profile#get_string
65
+ def get_string(section, key, opts = nil)
66
+ @profile.get_string(section, key, get_options(opts))
67
+ end
68
+
69
+ # call-seq:
70
+ # get_int(section, key)
71
+ # get_int(section, key, :default => -1)
72
+ # get_int(section, key, :cipher => true)
73
+ # get_int(section, key, :cipher => true, :default => -1)
74
+ #
75
+ # この ini ファイルから int 型データを読み込みます。
76
+ #
77
+ # See Also: SleipnirAPI::Profile#get_int
78
+ def get_int(section, key, opts = nil)
79
+ @profile.get_int(section, key, get_options(opts))
80
+ end
81
+
82
+ # call-seq:
83
+ # write_string(section, key, data)
84
+ # write_string(section, key, data, :cipher => true)
85
+ #
86
+ # <ini_dir>\script.ini に string 型データを書き込みます。
87
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
88
+ #
89
+ # * <tt>:cipher</tt> に true を指定すると暗号化してデータを書き込みます。
90
+ #
91
+ # See Also: SleipnirAPI::Profile#write_string
92
+ def write_string(section, key, data, opts = nil)
93
+ check_writable
94
+ @profile.write_string(section, key, data, write_options(opts))
95
+ end
96
+
97
+ # call-seq:
98
+ # write_int(section, key, data)
99
+ # write_int(section, key, data, :cipher => true)
100
+ #
101
+ # <ini_dir>\script.ini に int 型データを書き込みます。
102
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
103
+ #
104
+ # * <tt>:cipher</tt> に true を指定すると暗号化してデータを書き込みます。
105
+ #
106
+ # See Also: SleipnirAPI::Profile#write_int
107
+ def write_int(section, key, data, opts = nil)
108
+ check_writable
109
+ @profile.write_int(section, key, data, write_options(opts))
110
+ end
111
+
112
+ # <ini_dir>\script.ini から指定されたキーを削除します。
113
+ #
114
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
115
+ #
116
+ # See Also: SleipnirAPI::Profile#delete
117
+ def delete(section, key)
118
+ check_writable
119
+ @profile.delete(section, key)
120
+ end
121
+
122
+ # script.ini でない場合は SleipnirAPI::Profile::ReadOnlyError を raise します。
123
+ def check_writable
124
+ raise ReadOnlyError, "`#{path}' is not writable" if read_only?
125
+ end
126
+
127
+ # この ini ファイルのフルパスを返します。
128
+ def path
129
+ if script_ini?
130
+ @profile.script_ini_path
131
+ else
132
+ @profile.expand_user_path(@name)
133
+ end
134
+ end
135
+ alias to_s path
136
+
137
+ # <ini_dir>\script.ini なら true を返します。
138
+ def script_ini?
139
+ return true if @name.nil?
140
+ a = @profile.expand_user_path(@name)
141
+ b = @profile.script_ini_path
142
+ a.match(/\A#{Regexp.quote(b)}\z/i) ? true : false
143
+ end
144
+
145
+ # <ini_dir>\script.ini 以外なら true を返します。
146
+ def read_only?
147
+ not script_ini?
148
+ end
149
+
150
+ # 指定されたセクションを操作する Sleipnir::Profile::Section オブジェクトを返します。
151
+ #
152
+ # pnir = SleipnirAPI.connect
153
+ # proxy = pnir.profile.ini("Proxy.ini", :default => 123)
154
+ # sec = proxy.section("Proxy")
155
+ # sec.get_int("Count")
156
+ #
157
+ # See Also: #method_missing
158
+ def section(name, opts = nil)
159
+ Section.new(self, str(name), options(opts))
160
+ end
161
+
162
+ # メソッド名をセクション名とみなして Sleipnir::Profile::Section オブジェクトを返します。
163
+ #
164
+ # pnir = SleipnirAPI.connect
165
+ # proxy = pnir.profile.Proxy(:default => 123)
166
+ # sec = proxy.Proxy
167
+ # sec.get_int("Count")
168
+ #
169
+ # See Also: #section
170
+ def method_missing(mid, *args, &block)
171
+ section(mid.to_s, *args, &block)
172
+ end
173
+
174
+
175
+ def get_options(opts = nil)
176
+ args = options(opts, :cipher, :ini, :default)
177
+
178
+ r = {}
179
+ r[:default] = args.delete(:default) if args.key?(:default)
180
+ if script_ini?
181
+ r[:cipher] = args.delete(:cipher) if args.key?(:cipher)
182
+ else
183
+ r[:ini] = @name
184
+ end
185
+
186
+ unless args.empty?
187
+ raise ArgumentError, "Invalid argument: #{args.inspect} (#{path})"
188
+ end
189
+ r
190
+ end
191
+ private :get_options
192
+
193
+ def write_options(opts = nil)
194
+ r = get_options(opts)
195
+ r.delete(:default)
196
+ r
197
+ end
198
+ private :write_options
199
+
200
+ end
201
+ end
202
+ end