rb-scpt 1.0.1 → 1.0.2

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/bin/rb-scpt-1.0.1.gem +0 -0
  3. data/extconf.rb +12 -12
  4. data/rb-scpt.gemspec +10 -10
  5. data/sample/AB_export_vcard.rb +16 -16
  6. data/sample/AB_list_people_with_emails.rb +4 -4
  7. data/sample/Add_iCal_event.rb +12 -12
  8. data/sample/Create_daily_iCal_todos.rb +28 -28
  9. data/sample/Export_Address_Book_phone_numbers.rb +52 -52
  10. data/sample/Hello_world.rb +10 -10
  11. data/sample/List_iTunes_playlist_names.rb +3 -3
  12. data/sample/Make_Mail_message.rb +24 -24
  13. data/sample/Open_file_in_TextEdit.rb +5 -5
  14. data/sample/Organize_Mail_messages.rb +46 -46
  15. data/sample/Print_folder_tree.rb +5 -5
  16. data/sample/Select_all_HTML_files.rb +6 -6
  17. data/sample/Set_iChat_status.rb +12 -12
  18. data/sample/Simple_Finder_GUI_Scripting.rb +6 -6
  19. data/sample/Stagger_Finder_windows.rb +9 -9
  20. data/sample/TextEdit_demo.rb +71 -71
  21. data/sample/iTunes_top40_to_html.rb +28 -30
  22. data/src/SendThreadSafe.c +293 -293
  23. data/src/SendThreadSafe.h +108 -108
  24. data/src/lib/_aem/aemreference.rb +997 -998
  25. data/src/lib/_aem/codecs.rb +609 -610
  26. data/src/lib/_aem/connect.rb +197 -197
  27. data/src/lib/_aem/encodingsupport.rb +67 -67
  28. data/src/lib/_aem/findapp.rb +75 -75
  29. data/src/lib/_aem/mactypes.rb +241 -242
  30. data/src/lib/_aem/send.rb +268 -268
  31. data/src/lib/_aem/typewrappers.rb +52 -52
  32. data/src/lib/_appscript/defaultterminology.rb +266 -266
  33. data/src/lib/_appscript/referencerenderer.rb +230 -233
  34. data/src/lib/_appscript/reservedkeywords.rb +106 -106
  35. data/src/lib/_appscript/safeobject.rb +125 -125
  36. data/src/lib/_appscript/terminology.rb +448 -449
  37. data/src/lib/aem.rb +238 -238
  38. data/src/lib/kae.rb +1487 -1487
  39. data/src/lib/osax.rb +647 -647
  40. data/src/lib/rb-scpt.rb +1065 -1065
  41. data/src/rbae.c +595 -595
  42. data/test/test_aemreference.rb +104 -107
  43. data/test/test_appscriptcommands.rb +131 -134
  44. data/test/test_appscriptreference.rb +96 -99
  45. data/test/test_codecs.rb +166 -168
  46. data/test/test_findapp.rb +13 -16
  47. data/test/test_mactypes.rb +70 -72
  48. data/test/test_osax.rb +46 -48
  49. data/test/testall.sh +4 -4
  50. metadata +8 -7
@@ -5,55 +5,55 @@
5
5
  #
6
6
 
7
7
  module TypeWrappers
8
-
9
- class AETypeBase
10
-
11
- attr_reader :code
12
-
13
- def initialize(code)
14
- if not(code.is_a?(String) and code.length == 4)
15
- raise ArgumentError, "Code must be a four-character string: #{code.inspect}"
16
- end
17
- @code = code
18
- end
19
-
20
- def hash
21
- return @code.hash
22
- end
23
-
24
- def ==(val)
25
- return (self.equal?(val) or (val.class == self.class and val.code == @code))
26
- end
27
-
28
- alias_method :eql?, :==
29
-
30
- def to_s
31
- return "AEM::#{self.class::Name}.new(#{@code.inspect})"
32
- end
33
-
34
- def inspect
35
- return to_s
36
- end
37
- end
38
-
39
-
40
- class AEType < AETypeBase
41
- Name = 'AEType'
42
- end
43
-
44
-
45
- class AEEnum < AETypeBase
46
- Name = 'AEEnum'
47
- end
48
-
49
-
50
- class AEProp < AETypeBase
51
- Name = 'AEProp'
52
- end
53
-
54
-
55
- class AEKey < AETypeBase
56
- Name = 'AEKey'
57
- end
58
-
59
- end
8
+
9
+ class AETypeBase
10
+
11
+ attr_reader :code
12
+
13
+ def initialize(code)
14
+ if not(code.is_a?(String) and code.length == 4)
15
+ raise ArgumentError, "Code must be a four-character string: #{code.inspect}"
16
+ end
17
+ @code = code
18
+ end
19
+
20
+ def hash
21
+ return @code.hash
22
+ end
23
+
24
+ def ==(val)
25
+ return (self.equal?(val) or (val.class == self.class and val.code == @code))
26
+ end
27
+
28
+ alias_method :eql?, :==
29
+
30
+ def to_s
31
+ return "AEM::#{self.class::Name}.new(#{@code.inspect})"
32
+ end
33
+
34
+ def inspect
35
+ return to_s
36
+ end
37
+ end
38
+
39
+
40
+ class AEType < AETypeBase
41
+ Name = 'AEType'
42
+ end
43
+
44
+
45
+ class AEEnum < AETypeBase
46
+ Name = 'AEEnum'
47
+ end
48
+
49
+
50
+ class AEProp < AETypeBase
51
+ Name = 'AEProp'
52
+ end
53
+
54
+
55
+ class AEKey < AETypeBase
56
+ Name = 'AEKey'
57
+ end
58
+
59
+ end
@@ -5,273 +5,273 @@
5
5
  #
6
6
 
7
7
  module DefaultTerminology
8
- # Defines built-in terminology available for any application. When constructing the terminology tables for a particular application, the Terminology module will duplicate these tables and then add application-specific terms to create the finished lookup tables.
9
-
10
- require "aem"
11
-
12
- Enums = {
13
- 'yes ' => :yes,
14
- 'no ' => :no,
15
- 'ask ' => :ask,
16
-
17
- 'case' => :case,
18
- 'diac' => :diacriticals,
19
- 'expa' => :expansion,
20
- 'hyph' => :hyphens,
21
- 'punc' => :punctuation,
22
- 'whit' => :whitespace,
23
- 'nume' => :numeric_strings,
24
- 'rmte' => :application_responses,
25
- }
26
-
27
- Types = {
28
- '****' => :anything,
29
-
30
- 'bool' => :boolean,
31
-
32
- 'shor' => :short_integer,
33
- 'long' => :integer,
34
- 'magn' => :unsigned_integer,
35
- 'comp' => :double_integer,
36
-
37
- 'fixd' => :fixed,
38
- 'lfxd' => :long_fixed,
39
- 'decm' => :decimal_struct,
40
-
41
- 'sing' => :short_float,
42
- 'doub' => :float,
43
- 'exte' => :extended_float,
44
- 'ldbl' => :float_128bit,
45
-
46
- 'TEXT' => :string,
47
- 'cstr' => :c_string,
48
- 'pstr' => :pascal_string,
49
- 'STXT' => :styled_text,
50
- 'tsty' => :text_style_info,
51
- 'styl' => :styled_clipboard_text,
52
- 'encs' => :encoded_string,
53
- 'psct' => :writing_code,
54
- 'intl' => :international_writing_code,
55
- 'itxt' => :international_text,
56
- 'sutx' => :styled_unicode_text,
57
- 'utxt' => :unicode_text,
58
- 'utf8' => :utf8_text, # typeUTF8Text
59
- 'ut16' => :utf16_text, # typeUTF16ExternalRepresentation
60
-
61
- 'vers' => :version,
62
- 'ldt ' => :date,
63
- 'list' => :list,
64
- 'reco' => :record,
65
- 'tdta' => :data,
66
- 'scpt' => :script,
67
-
68
- 'insl' => :location_reference,
69
- 'obj ' => :reference,
70
-
71
- 'alis' => :alias,
72
- 'fsrf' => :file_ref,
73
- 'fss ' => :file_specification,
74
- 'furl' => :file_url,
75
-
76
- 'QDpt' => :point,
77
- 'qdrt' => :bounding_rectangle,
78
- 'fpnt' => :fixed_point,
79
- 'frct' => :fixed_rectangle,
80
- 'lpnt' => :long_point,
81
- 'lrct' => :long_rectangle,
82
- 'lfpt' => :long_fixed_point,
83
- 'lfrc' => :long_fixed_rectangle,
84
-
85
- 'EPS ' => :EPS_picture,
86
- 'GIFf' => :GIF_picture,
87
- 'JPEG' => :JPEG_picture,
88
- 'PICT' => :PICT_picture,
89
- 'TIFF' => :TIFF_picture,
90
- 'cRGB' => :RGB_color,
91
- 'tr16' => :RGB16_color,
92
- 'tr96' => :RGB96_color,
93
- 'cgtx' => :graphic_text,
94
- 'clrt' => :color_table,
95
- 'tpmm' => :pixel_map_record,
96
-
97
- 'best' => :best,
98
- 'type' => :type_class,
99
- 'enum' => :enumerator,
100
- 'prop' => :property,
101
-
102
- # AEAddressDesc types
103
-
104
- 'port' => :mach_port,
105
- 'kpid' => :kernel_process_id,
106
- 'bund' => :application_bundle_id,
107
- 'psn ' => :process_serial_number,
108
- 'sign' => :application_signature,
109
- 'aprl' => :application_url,
110
-
111
- # misc.
112
-
113
- 'msng' => :missing_value,
114
-
115
- 'cobj' => :item,
116
-
117
- 'null' => :null,
118
-
119
- 'mLoc' => :machine_location,
120
- 'mach' => :machine,
121
-
122
- 'tdas' => :dash_style,
123
- 'trot' => :rotation,
124
-
125
- 'suin' => :suite_info,
126
- 'gcli' => :class_info,
127
- 'pinf' => :property_info,
128
- 'elin' => :element_info,
129
- 'evin' => :event_info,
130
- 'pmin' => :parameter_info,
131
-
132
- # unit types
133
-
134
- 'cmtr' => :centimeters,
135
- 'metr' => :meters,
136
- 'kmtr' => :kilometers,
137
- 'inch' => :inches,
138
- 'feet' => :feet,
139
- 'yard' => :yards,
140
- 'mile' => :miles,
141
-
142
- 'sqrm' => :square_meters,
143
- 'sqkm' => :square_kilometers,
144
- 'sqft' => :square_feet,
145
- 'sqyd' => :square_yards,
146
- 'sqmi' => :square_miles,
147
-
148
- 'ccmt' => :cubic_centimeters,
149
- 'cmet' => :cubic_meters,
150
- 'cuin' => :cubic_inches,
151
- 'cfet' => :cubic_feet,
152
- 'cyrd' => :cubic_yards,
153
-
154
- 'litr' => :liters,
155
- 'qrts' => :quarts,
156
- 'galn' => :gallons,
157
-
158
- 'gram' => :grams,
159
- 'kgrm' => :kilograms,
160
- 'ozs ' => :ounces,
161
- 'lbs ' => :pounds,
162
-
163
- 'degc' => :degrees_Celsius,
164
- 'degf' => :degrees_Fahrenheit,
165
- 'degk' => :degrees_Kelvin,
166
-
167
- # month and weekday
168
-
169
- 'jan ' => :January,
170
- 'feb ' => :February,
171
- 'mar ' => :March,
172
- 'apr ' => :April,
173
- 'may ' => :May,
174
- 'jun ' => :June,
175
- 'jul ' => :July,
176
- 'aug ' => :August,
177
- 'sep ' => :September,
178
- 'oct ' => :October,
179
- 'nov ' => :November,
180
- 'dec ' => :December,
181
-
182
- 'sun ' => :Sunday,
183
- 'mon ' => :Monday,
184
- 'tue ' => :Tuesday,
185
- 'wed ' => :Wednesday,
186
- 'thu ' => :Thursday,
187
- 'fri ' => :Friday,
188
- 'sat ' => :Saturday,
189
- }
190
-
191
- Properties = {
8
+ # Defines built-in terminology available for any application. When constructing the terminology tables for a particular application, the Terminology module will duplicate these tables and then add application-specific terms to create the finished lookup tables.
9
+
10
+ require "aem"
11
+
12
+ Enums = {
13
+ 'yes ' => :yes,
14
+ 'no ' => :no,
15
+ 'ask ' => :ask,
16
+
17
+ 'case' => :case,
18
+ 'diac' => :diacriticals,
19
+ 'expa' => :expansion,
20
+ 'hyph' => :hyphens,
21
+ 'punc' => :punctuation,
22
+ 'whit' => :whitespace,
23
+ 'nume' => :numeric_strings,
24
+ 'rmte' => :application_responses,
25
+ }
26
+
27
+ Types = {
28
+ '****' => :anything,
29
+
30
+ 'bool' => :boolean,
31
+
32
+ 'shor' => :short_integer,
33
+ 'long' => :integer,
34
+ 'magn' => :unsigned_integer,
35
+ 'comp' => :double_integer,
36
+
37
+ 'fixd' => :fixed,
38
+ 'lfxd' => :long_fixed,
39
+ 'decm' => :decimal_struct,
40
+
41
+ 'sing' => :short_float,
42
+ 'doub' => :float,
43
+ 'exte' => :extended_float,
44
+ 'ldbl' => :float_128bit,
45
+
46
+ 'TEXT' => :string,
47
+ 'cstr' => :c_string,
48
+ 'pstr' => :pascal_string,
49
+ 'STXT' => :styled_text,
50
+ 'tsty' => :text_style_info,
51
+ 'styl' => :styled_clipboard_text,
52
+ 'encs' => :encoded_string,
53
+ 'psct' => :writing_code,
54
+ 'intl' => :international_writing_code,
55
+ 'itxt' => :international_text,
56
+ 'sutx' => :styled_unicode_text,
57
+ 'utxt' => :unicode_text,
58
+ 'utf8' => :utf8_text, # typeUTF8Text
59
+ 'ut16' => :utf16_text, # typeUTF16ExternalRepresentation
60
+
61
+ 'vers' => :version,
62
+ 'ldt ' => :date,
63
+ 'list' => :list,
64
+ 'reco' => :record,
65
+ 'tdta' => :data,
66
+ 'scpt' => :script,
67
+
68
+ 'insl' => :location_reference,
69
+ 'obj ' => :reference,
70
+
71
+ 'alis' => :alias,
72
+ 'fsrf' => :file_ref,
73
+ 'fss ' => :file_specification,
74
+ 'furl' => :file_url,
75
+
76
+ 'QDpt' => :point,
77
+ 'qdrt' => :bounding_rectangle,
78
+ 'fpnt' => :fixed_point,
79
+ 'frct' => :fixed_rectangle,
80
+ 'lpnt' => :long_point,
81
+ 'lrct' => :long_rectangle,
82
+ 'lfpt' => :long_fixed_point,
83
+ 'lfrc' => :long_fixed_rectangle,
84
+
85
+ 'EPS ' => :EPS_picture,
86
+ 'GIFf' => :GIF_picture,
87
+ 'JPEG' => :JPEG_picture,
88
+ 'PICT' => :PICT_picture,
89
+ 'TIFF' => :TIFF_picture,
90
+ 'cRGB' => :RGB_color,
91
+ 'tr16' => :RGB16_color,
92
+ 'tr96' => :RGB96_color,
93
+ 'cgtx' => :graphic_text,
94
+ 'clrt' => :color_table,
95
+ 'tpmm' => :pixel_map_record,
96
+
97
+ 'best' => :best,
98
+ 'type' => :type_class,
99
+ 'enum' => :enumerator,
100
+ 'prop' => :property,
101
+
102
+ # AEAddressDesc types
103
+
104
+ 'port' => :mach_port,
105
+ 'kpid' => :kernel_process_id,
106
+ 'bund' => :application_bundle_id,
107
+ 'psn ' => :process_serial_number,
108
+ 'sign' => :application_signature,
109
+ 'aprl' => :application_url,
110
+
111
+ # misc.
112
+
113
+ 'msng' => :missing_value,
114
+
115
+ 'cobj' => :item,
116
+
117
+ 'null' => :null,
118
+
119
+ 'mLoc' => :machine_location,
120
+ 'mach' => :machine,
121
+
122
+ 'tdas' => :dash_style,
123
+ 'trot' => :rotation,
124
+
125
+ 'suin' => :suite_info,
126
+ 'gcli' => :class_info,
127
+ 'pinf' => :property_info,
128
+ 'elin' => :element_info,
129
+ 'evin' => :event_info,
130
+ 'pmin' => :parameter_info,
131
+
132
+ # unit types
133
+
134
+ 'cmtr' => :centimeters,
135
+ 'metr' => :meters,
136
+ 'kmtr' => :kilometers,
137
+ 'inch' => :inches,
138
+ 'feet' => :feet,
139
+ 'yard' => :yards,
140
+ 'mile' => :miles,
141
+
142
+ 'sqrm' => :square_meters,
143
+ 'sqkm' => :square_kilometers,
144
+ 'sqft' => :square_feet,
145
+ 'sqyd' => :square_yards,
146
+ 'sqmi' => :square_miles,
147
+
148
+ 'ccmt' => :cubic_centimeters,
149
+ 'cmet' => :cubic_meters,
150
+ 'cuin' => :cubic_inches,
151
+ 'cfet' => :cubic_feet,
152
+ 'cyrd' => :cubic_yards,
153
+
154
+ 'litr' => :liters,
155
+ 'qrts' => :quarts,
156
+ 'galn' => :gallons,
157
+
158
+ 'gram' => :grams,
159
+ 'kgrm' => :kilograms,
160
+ 'ozs ' => :ounces,
161
+ 'lbs ' => :pounds,
162
+
163
+ 'degc' => :degrees_Celsius,
164
+ 'degf' => :degrees_Fahrenheit,
165
+ 'degk' => :degrees_Kelvin,
166
+
167
+ # month and weekday
168
+
169
+ 'jan ' => :January,
170
+ 'feb ' => :February,
171
+ 'mar ' => :March,
172
+ 'apr ' => :April,
173
+ 'may ' => :May,
174
+ 'jun ' => :June,
175
+ 'jul ' => :July,
176
+ 'aug ' => :August,
177
+ 'sep ' => :September,
178
+ 'oct ' => :October,
179
+ 'nov ' => :November,
180
+ 'dec ' => :December,
181
+
182
+ 'sun ' => :Sunday,
183
+ 'mon ' => :Monday,
184
+ 'tue ' => :Tuesday,
185
+ 'wed ' => :Wednesday,
186
+ 'thu ' => :Thursday,
187
+ 'fri ' => :Friday,
188
+ 'sat ' => :Saturday,
189
+ }
190
+
191
+ Properties = {
192
192
  'pcls' => :class_,
193
193
  'pALL' => :properties_,
194
194
  'ID ' => :id_,
195
- }
196
-
197
- Elements = {
198
- 'cobj' => :items,
199
- }
200
-
201
- Commands = {
202
- :quit => ['aevtquit', {
203
- :saving => 'savo',
204
- }],
205
- :activate => ['miscactv', {
206
- }],
207
- :run => ['aevtoapp', {
208
- }],
209
- :launch => ['ascrnoop', {
210
- }],
211
- :open => ['aevtodoc', {
212
- }],
213
- :get => ['coregetd', {
214
- }],
215
- :print => ['aevtpdoc', {
216
- }],
217
- :set => ['coresetd', {
218
- :to => 'data',
219
- }],
220
- :reopen => ['aevtrapp', {
221
- }],
222
- :open_location => ['GURLGURL', {
223
- :window => 'WIND',
224
- }],
225
- }
226
-
227
- #######
228
- # TypeByCode and TypeByName tables are used to convert Ruby Symbols to and from AEDescs of typeType, typeEnum and typeProperty.
229
-
230
- TypeByCode = {} # used to decode class (typeType) and enumerator (typeEnum) descriptors
231
- TypeByName = {} # used to encode class and enumerator keywords
232
- TypeCodeByName = {} # used to check for name collisions
233
-
234
- Enums.each do |code, name|
235
- TypeByCode[code] = name
236
- TypeByName[name] = AEM::AEEnum.new(code)
237
- TypeCodeByName[name.to_s] = code
238
- end
239
-
240
- [Types, Properties].each do |table|
241
- table.each do |code, name|
242
- TypeByCode[code] = name
243
- TypeByName[name] = AEM::AEType.new(code)
244
- TypeCodeByName[name.to_s] = code
245
- end
246
- end
247
-
248
- #######
249
- # ReferenceByCode and ReferenceByName tables are used to convert between appscript- and aem-style references
250
-
251
- ReferenceByCode = {} # used by ReferenceRenderer module to convert property and element four-char codes to human readable names
252
- ReferenceByName = {} # used to convert appscript-style references and commands to their aem equivalents
253
-
254
- Properties.each do |code, name|
255
- ReferenceByCode['p' + code] = name.to_s
256
- ReferenceByName[name] = [:property, code]
257
- end
258
-
259
- Elements.each do |code, name|
260
- ReferenceByCode['e' + code] = name.to_s
261
- ReferenceByName[name] = [:element, code]
262
- end
263
-
264
- Commands.each do |name, info|
265
- ReferenceByName[name] = [:command, info]
266
- end
267
-
268
- #######
269
- # CommandCodeByName; used by Terminology._make_reference_table to check for any collisions between standard and application-defined commands where the command names are the same but the codes are different
270
-
271
- CommandCodeByName = {} # {'quit' => 'aevtquit', 'activate' => 'miscactv',...}
272
- ReferenceByName.each do |name, info|
273
- if info[0] == :command
274
- CommandCodeByName[name.to_s] = info[1][0]
275
- end
276
- end
195
+ }
196
+
197
+ Elements = {
198
+ 'cobj' => :items,
199
+ }
200
+
201
+ Commands = {
202
+ :quit => ['aevtquit', {
203
+ :saving => 'savo',
204
+ }],
205
+ :activate => ['miscactv', {
206
+ }],
207
+ :run => ['aevtoapp', {
208
+ }],
209
+ :launch => ['ascrnoop', {
210
+ }],
211
+ :open => ['aevtodoc', {
212
+ }],
213
+ :get => ['coregetd', {
214
+ }],
215
+ :print => ['aevtpdoc', {
216
+ }],
217
+ :set => ['coresetd', {
218
+ :to => 'data',
219
+ }],
220
+ :reopen => ['aevtrapp', {
221
+ }],
222
+ :open_location => ['GURLGURL', {
223
+ :window => 'WIND',
224
+ }],
225
+ }
226
+
227
+ #######
228
+ # TypeByCode and TypeByName tables are used to convert Ruby Symbols to and from AEDescs of typeType, typeEnum and typeProperty.
229
+
230
+ TypeByCode = {} # used to decode class (typeType) and enumerator (typeEnum) descriptors
231
+ TypeByName = {} # used to encode class and enumerator keywords
232
+ TypeCodeByName = {} # used to check for name collisions
233
+
234
+ Enums.each do |code, name|
235
+ TypeByCode[code] = name
236
+ TypeByName[name] = AEM::AEEnum.new(code)
237
+ TypeCodeByName[name.to_s] = code
238
+ end
239
+
240
+ [Types, Properties].each do |table|
241
+ table.each do |code, name|
242
+ TypeByCode[code] = name
243
+ TypeByName[name] = AEM::AEType.new(code)
244
+ TypeCodeByName[name.to_s] = code
245
+ end
246
+ end
247
+
248
+ #######
249
+ # ReferenceByCode and ReferenceByName tables are used to convert between appscript- and aem-style references
250
+
251
+ ReferenceByCode = {} # used by ReferenceRenderer module to convert property and element four-char codes to human readable names
252
+ ReferenceByName = {} # used to convert appscript-style references and commands to their aem equivalents
253
+
254
+ Properties.each do |code, name|
255
+ ReferenceByCode['p' + code] = name.to_s
256
+ ReferenceByName[name] = [:property, code]
257
+ end
258
+
259
+ Elements.each do |code, name|
260
+ ReferenceByCode['e' + code] = name.to_s
261
+ ReferenceByName[name] = [:element, code]
262
+ end
263
+
264
+ Commands.each do |name, info|
265
+ ReferenceByName[name] = [:command, info]
266
+ end
267
+
268
+ #######
269
+ # CommandCodeByName; used by Terminology._make_reference_table to check for any collisions between standard and application-defined commands where the command names are the same but the codes are different
270
+
271
+ CommandCodeByName = {} # {'quit' => 'aevtquit', 'activate' => 'miscactv',...}
272
+ ReferenceByName.each do |name, info|
273
+ if info[0] == :command
274
+ CommandCodeByName[name.to_s] = info[1][0]
275
+ end
276
+ end
277
277
  end