open 0.1.30 → 0.2.22

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 (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +110 -31
  3. data/bin/open +1 -1
  4. data/bin/open_in_browser +1 -1
  5. data/doc/README.gen +72 -8
  6. data/doc/deprecated_code/deprecated_code.md +26 -0
  7. data/img/open_logo.png +0 -0
  8. data/lib/open/base/base.rb +265 -128
  9. data/lib/open/books/README.md +8 -0
  10. data/lib/open/books/books.rb +100 -0
  11. data/lib/open/constants/constants.rb +86 -8
  12. data/lib/open/in_browser/in_browser.rb +501 -319
  13. data/lib/open/in_editor/in_editor.rb +367 -162
  14. data/lib/open/last/last.rb +14 -12
  15. data/lib/open/last_url/last_url.rb +4 -3
  16. data/lib/open/nano_open/nano_open.rb +30 -5
  17. data/lib/open/{open.rb → open/open.rb} +596 -654
  18. data/lib/open/project/project.rb +3 -2
  19. data/lib/open/requires/failsafe_require_of_beautiful_url.rb +9 -0
  20. data/lib/open/requires/require_the_project.rb +2 -2
  21. data/lib/open/requires/require_yaml.rb +13 -0
  22. data/lib/open/these_files/these_files.rb +1 -1
  23. data/lib/open/toplevel_methods/browser.rb +71 -0
  24. data/lib/open/toplevel_methods/delay.rb +23 -0
  25. data/lib/open/toplevel_methods/e.rb +14 -0
  26. data/lib/open/toplevel_methods/editor.rb +41 -0
  27. data/lib/open/toplevel_methods/host_os.rb +25 -0
  28. data/lib/open/toplevel_methods/is_on_roebe.rb +16 -0
  29. data/lib/open/toplevel_methods/is_on_windows.rb +26 -0
  30. data/lib/open/toplevel_methods/misc.rb +50 -0
  31. data/lib/open/version/version.rb +2 -2
  32. data/lib/open/with_delay/with_delay.rb +10 -11
  33. data/open.gemspec +3 -3
  34. data/test/testing_open.rb +1 -1
  35. data/test/testing_open_in_browser.rb +16 -0
  36. data/test/testing_open_via_launchy.rb +3 -0
  37. data/test/testing_shortcuts.rb +3 -0
  38. metadata +25 -9
  39. data/lib/open/toplevel_code/toplevel_code.rb +0 -189
@@ -2,64 +2,103 @@
2
2
  # Encoding: UTF-8
3
3
  # frozen_string_literal: true
4
4
  # =========================================================================== #
5
+ # === Open::Base
6
+ #
7
+ # Usage example:
8
+ #
9
+ # Open::Base.new(ARGV)
10
+ #
11
+ # =========================================================================== #
5
12
  # require 'open/base/base.rb'
6
- # < Base
13
+ # < ::Open::Base
7
14
  # =========================================================================== #
8
15
  module Open
9
16
 
10
17
  class Base # === Open::Base
11
18
 
12
- require 'yaml'
19
+ alias e puts
13
20
 
14
21
  require 'fileutils'
15
-
16
- begin
17
- require 'colours'
18
- include Colours::E
19
- rescue LoadError; end
20
-
21
- begin
22
- require 'beautiful_url'
23
- rescue LoadError
24
- # puts 'BeautifulUrl is not available.'
25
- end
22
+ require 'open/requires/require_yaml.rb'
23
+ require 'open/constants/constants.rb'
24
+ require 'open/project/project.rb'
25
+ require 'open/toplevel_methods/delay.rb'
26
+ require 'open/toplevel_methods/misc.rb'
27
+ require 'open/toplevel_methods/host_os.rb'
26
28
 
27
29
  begin
28
30
  require 'opn'
29
31
  rescue LoadError; end
30
32
 
31
33
  begin
32
- require 'convert_global_env'
34
+ require 'roebe/classes/find_expanded_alias.rb'
33
35
  rescue LoadError; end
34
36
 
35
37
  begin
36
- require 'roebe/classes/find_expanded_alias.rb'
38
+ require 'colours/html_colours'
39
+ include Colours::E
37
40
  rescue LoadError; end
38
41
 
39
- require 'open/constants/constants.rb'
40
- require 'open/toplevel_code/toplevel_code.rb'
41
-
42
42
  # ========================================================================= #
43
43
  # === NAMESPACE
44
44
  # ========================================================================= #
45
45
  NAMESPACE = inspect
46
46
 
47
47
  # ========================================================================= #
48
- # === rev
48
+ # === initialize
49
49
  # ========================================================================= #
50
- def rev
51
- if Object.const_defined? :Colours
52
- ::Colours.rev
53
- else
54
- ''
55
- end
50
+ def initialize(i = ARGV)
51
+ set_commandline_arguments(i)
52
+ end
53
+
54
+ # ========================================================================= #
55
+ # === reset (reset tag)
56
+ # ========================================================================= #
57
+ def reset
58
+ # ======================================================================= #
59
+ # === @namespace
60
+ # ======================================================================= #
61
+ @namespace = NAMESPACE
62
+ # ======================================================================= #
63
+ # === @be_verbose
64
+ # ======================================================================= #
65
+ @be_verbose = true
66
+ end
67
+
68
+ require 'open/toplevel_methods/is_on_windows.rb'
69
+ # ========================================================================= #
70
+ # === is_on_windows?
71
+ # ========================================================================= #
72
+ def is_on_windows?(
73
+ i = ::Open.host_os?
74
+ )
75
+ ::Open.is_on_windows?(i)
76
+ end; alias on_windows? is_on_windows? # === on_windows?
77
+
78
+ # ========================================================================= #
79
+ # === return_pwd
80
+ # ========================================================================= #
81
+ def return_pwd
82
+ "#{Dir.pwd}/".squeeze('/')
83
+ end
84
+
85
+ # ========================================================================= #
86
+ # == snakecase
87
+ # ========================================================================= #
88
+ def snakecase(i)
89
+ i.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
90
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
91
+ tr('-', '_').
92
+ gsub(/\s/, '_').
93
+ gsub(/__+/, '_').
94
+ downcase
56
95
  end
57
96
 
58
97
  # ========================================================================= #
59
98
  # === simp
60
99
  # ========================================================================= #
61
100
  def simp(i = '')
62
- if Object.const_defined? :Colours
101
+ if Object.const_defined?(:Colours) and ::Colours.respond_to?(:simp)
63
102
  return ::Colours.simp(i)
64
103
  else
65
104
  return i
@@ -70,7 +109,7 @@ class Base # === Open::Base
70
109
  # === sfancy
71
110
  # ========================================================================= #
72
111
  def sfancy(i = '')
73
- if Object.const_defined? :Colours
112
+ if Object.const_defined?(:Colours) and ::Colours.respond_to?(:sfancy)
74
113
  return ::Colours.sfancy(i)
75
114
  else
76
115
  return i
@@ -81,7 +120,7 @@ class Base # === Open::Base
81
120
  # === steelblue
82
121
  # ========================================================================= #
83
122
  def steelblue(i = '')
84
- if Object.const_defined? :Colours
123
+ if Object.const_defined?(:Colours) and ::Colours.respond_to?(:steelblue)
85
124
  return ::Colours.steelblue(i)
86
125
  else
87
126
  return i
@@ -110,7 +149,7 @@ class Base # === Open::Base
110
149
  # === sfile
111
150
  # ========================================================================= #
112
151
  def sfile(i = '')
113
- if Object.const_defined? :Colours
152
+ if Object.const_defined?(:Colours) and ::Colours.respond_to?(:sfile)
114
153
  return ::Colours.sfile(i)
115
154
  else
116
155
  return i
@@ -125,78 +164,56 @@ class Base # === Open::Base
125
164
  end
126
165
 
127
166
  # ========================================================================= #
128
- # === esystem
129
- #
130
- # This is a bit of an ad-hoc fix to make this work on windows as well.
167
+ # === host_os?
131
168
  #
132
- # Eventually may have to rewrite the method a little bit, but for now
133
- # (September 2021) this has to suffice.
169
+ # Return the host-operating system via this method.
134
170
  # ========================================================================= #
135
- def esystem(
136
- i, do_show_the_command_that_will_be_used = true
137
- )
138
- if is_on_windows?
139
- # i = i.to_s.sub(/\\/,'\\') if i.include?("\\")
140
- i = '"'+i.to_s+'"' if i.include?(' ')
141
- end
142
- e i if do_show_the_command_that_will_be_used
143
- system(i)
171
+ def host_os?
172
+ ::Open.host_os?
144
173
  end
145
174
 
175
+ require 'open/toplevel_methods/is_on_roebe.rb'
146
176
  # ========================================================================= #
147
- # === sanitize
177
+ # === is_on_roebe?
148
178
  # ========================================================================= #
149
- def sanitize(i)
150
- return i unless Object.const_defined? :ConvertGlobalEnv
151
- begin
152
- return ConvertGlobalEnv.convert(i)
153
- rescue NoMethodError
154
- i
155
- end
179
+ def is_on_roebe?
180
+ ::Open.is_on_roebe?
156
181
  end
157
182
 
158
183
  # ========================================================================= #
159
- # === return_pwd
184
+ # === namespace?
160
185
  # ========================================================================= #
161
- def return_pwd
162
- "#{Dir.pwd}/".squeeze('/')
186
+ def namespace?
187
+ @namespace
163
188
  end
164
189
 
165
190
  # ========================================================================= #
166
- # == snakecase
191
+ # === ecomment
167
192
  # ========================================================================= #
168
- def snakecase(i)
169
- i.gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
170
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
171
- tr('-', '_').
172
- gsub(/\s/, '_').
173
- gsub(/__+/, '_').
174
- downcase
193
+ def ecomment(i = '')
194
+ ::Colours.ecomment(i)
175
195
  end
176
196
 
197
+ require 'open/toplevel_methods/browser.rb'
177
198
  # ========================================================================= #
178
- # === reset (reset tag)
199
+ # === use_which_browser?
179
200
  # ========================================================================= #
180
- def reset
181
- # ======================================================================= #
182
- # === @namespace
183
- # ======================================================================= #
184
- @namespace = NAMESPACE
185
- # ======================================================================= #
186
- # === @be_verbose
187
- # ======================================================================= #
188
- @be_verbose = true
201
+ def use_which_browser?
202
+ ::Open.use_which_browser?
189
203
  end
190
204
 
191
205
  # ========================================================================= #
192
- # === opnn
206
+ # === mkdir (mkdir tag)
193
207
  # ========================================================================= #
194
- def opnn(
195
- i = { namespace: @namespace }
196
- )
197
- if Object.const_defined? :Opn
198
- Opn.opn(i)
199
- end
208
+ def mkdir(i)
209
+ FileUtils.mkdir_p(i)
210
+ end
211
+
212
+ # ========================================================================= #
213
+ # === touch (touch tag)
214
+ # ========================================================================= #
215
+ def touch(i)
216
+ FileUtils.touch(i)
200
217
  end
201
218
 
202
219
  # ========================================================================= #
@@ -208,6 +225,22 @@ class Base # === Open::Base
208
225
  @commandline_arguments = [i].flatten.compact
209
226
  end
210
227
 
228
+ # ========================================================================= #
229
+ # === commandline_arguments?
230
+ # ========================================================================= #
231
+ def commandline_arguments?
232
+ @commandline_arguments
233
+ end
234
+
235
+ # ========================================================================= #
236
+ # === commandline_arguments_without_hyphens
237
+ # ========================================================================= #
238
+ def commandline_arguments_without_hyphens
239
+ @commandline_arguments.reject {|entry|
240
+ entry.start_with?('--')
241
+ }
242
+ end
243
+
211
244
  # ========================================================================= #
212
245
  # === first_argument?
213
246
  # ========================================================================= #
@@ -215,94 +248,158 @@ class Base # === Open::Base
215
248
  @commandline_arguments.first
216
249
  end
217
250
 
251
+ require 'open/toplevel_methods/editor.rb'
218
252
  # ========================================================================= #
219
- # === rds
253
+ # === use_which_editor?
220
254
  # ========================================================================= #
221
- def rds(i)
222
- i.squeeze('/')
255
+ def use_which_editor?
256
+ ::Open.use_which_editor?
223
257
  end
224
258
 
225
259
  # ========================================================================= #
226
- # === mkdir
260
+ # === opnn
227
261
  # ========================================================================= #
228
- def mkdir(i)
229
- FileUtils.mkdir_p(i)
262
+ def opnn(
263
+ i = {
264
+ namespace: @namespace
265
+ }
266
+ )
267
+ if Object.const_defined? :Opn
268
+ Opn.opn(i)
269
+ end
230
270
  end
231
271
 
232
272
  # ========================================================================= #
233
- # === touch
273
+ # === use_which_delay?
234
274
  # ========================================================================= #
235
- def touch(i)
236
- FileUtils.touch(i)
275
+ def use_which_delay?
276
+ Open.use_which_delay?.to_f
237
277
  end
238
278
 
239
279
  # ========================================================================= #
240
- # === use_which_editor?
280
+ # === opne
241
281
  # ========================================================================= #
242
- def use_which_editor?
243
- ::Open.use_which_editor?
282
+ def opne(i = '')
283
+ opn(namespace: @namespace); e i
244
284
  end
245
285
 
286
+ begin
287
+ require 'beautiful_url'
288
+ rescue LoadError; end
246
289
  # ========================================================================= #
247
- # === use_which_browser?
290
+ # === beautiful_url
291
+ #
292
+ # Wrapper-method towards BeautifulUrl.
248
293
  # ========================================================================= #
249
- def use_which_browser?
250
- ::Open.use_which_browser?
294
+ def beautiful_url(i)
295
+ if beautiful_url_is_available?
296
+ i = BeautifulUrl::BeautifulUrl.new(i).results?
297
+ end
298
+ return i
251
299
  end
252
300
 
253
301
  # ========================================================================= #
254
- # === this_file_was_not_found
255
- #
256
- # Use this whenever we did not find any file.
302
+ # === beautiful_url_is_available?
257
303
  # ========================================================================= #
258
- def this_file_was_not_found(i)
259
- e "No file called `#{sfile(i)}` was found. It "\
260
- "is assumed that it does not exist."
261
- end; alias no_file_exists_at this_file_was_not_found # === no_file_exists_at
262
- alias no_file_was_found_at this_file_was_not_found # === no_file_was_found_at
304
+ def beautiful_url_is_available?
305
+ Object.const_defined? :BeautifulUrl
306
+ end; alias is_beautiful_url_available? beautiful_url_is_available? # === is_beautiful_url_available?
263
307
 
264
308
  # ========================================================================= #
265
- # === host_os?
266
- #
267
- # Return the host-operating system via this method.
309
+ # === try_to_require_the_beautiful_url_project
268
310
  # ========================================================================= #
269
- def host_os?
270
- ::Open.host_os?
311
+ def try_to_require_the_beautiful_url_project
312
+ unless Object.const_defined? :BeautifulUrl
313
+ begin
314
+ require 'open/requires/failsafe_require_of_beautiful_url.rb'
315
+ rescue LoadError; end
316
+ end
271
317
  end
272
318
 
273
319
  # ========================================================================= #
274
- # === is_on_windows?
320
+ # === file_load_default_browser?
275
321
  # ========================================================================= #
276
- def is_on_windows?(i = host_os?)
277
- ::Open.is_on_windows?(i)
278
- end; alias on_windows? is_on_windows? # === on_windows?
322
+ def file_load_default_browser?
323
+ # ======================================================================= #
324
+ # The .yml file will hold which browser is to be used by default.
325
+ # ======================================================================= #
326
+ _ = "#{::Open.project_base_directory?}yaml/use_this_browser.yml"
327
+ if File.exist? _
328
+ return YAML.load_file(_)
329
+ else
330
+ return 'chrome'
331
+ end
332
+ end
279
333
 
280
334
  # ========================================================================= #
281
- # === is_on_roebe?
335
+ # === file_load_default_editor?
282
336
  # ========================================================================= #
283
- def is_on_roebe?
284
- ENV['IS_ROEBE'].to_s == '1'
337
+ def file_load_default_editor?
338
+ # ======================================================================= #
339
+ # The .yml file will hold which editor is to be used by default.
340
+ # ======================================================================= #
341
+ _ = "#{::Open.project_base_directory?}yaml/use_this_editor.yml"
342
+ if File.exist? _
343
+ return YAML.load_file(_)
344
+ else
345
+ return 'bluefish'
346
+ end
285
347
  end
286
348
 
349
+ begin
350
+ require 'convert_global_env'
351
+ rescue LoadError; end
287
352
  # ========================================================================= #
288
- # === ecomment
353
+ # === sanitize_global_environment
354
+ #
355
+ # This method bundles together functionality that ConvertGlobalEnv
356
+ # can handle.
289
357
  # ========================================================================= #
290
- def ecomment(i = '')
291
- ::Colours.ecomment(i)
292
- end
358
+ def sanitize_global_environment(i)
359
+ return i unless Object.const_defined? :ConvertGlobalEnv
360
+ begin
361
+ return ConvertGlobalEnv.convert(i)
362
+ rescue NoMethodError
363
+ return i
364
+ end
365
+ end; alias sanitize sanitize_global_environment # === sanitize
293
366
 
294
367
  # ========================================================================= #
295
- # === beautiful_url
368
+ # === consider_padding
296
369
  #
297
- # Wrapper-method towards BeautifulUrl.
370
+ # Simply add a surrounding '"' to the given input, so that any resulting
371
+ # system() call will still work if we have awkward filenames.
298
372
  # ========================================================================= #
299
- def beautiful_url(i)
300
- if Object.const_defined? :BeautifulUrl
301
- i = BeautifulUrl::BeautifulUrl.new(i).results?
373
+ def consider_padding(i)
374
+ if i.include?(' ') or i.include?('(')
375
+ i = '"'+i+'"'
302
376
  end
303
- return i
377
+ return i # Always return the input, no matter if modified or not.
378
+ end
379
+
380
+ # ========================================================================= #
381
+ # === rds
382
+ # ========================================================================= #
383
+ def rds(i)
384
+ i.squeeze('/')
385
+ end
386
+
387
+ # ========================================================================= #
388
+ # === append_array_to_commandline_arguments
389
+ # ========================================================================= #
390
+ def append_array_to_commandline_arguments(i)
391
+ i = [i].flatten.compact
392
+ @commandline_arguments << i
393
+ @commandline_arguments.flatten!
304
394
  end
305
395
 
396
+ # ========================================================================= #
397
+ # === create_the_internal_hash
398
+ # ========================================================================= #
399
+ def create_the_internal_hash
400
+ @internal_hash = {}
401
+ end; alias reset_the_internal_hash create_the_internal_hash # === reset_the_internal_hash
402
+
306
403
  # ========================================================================= #
307
404
  # === infer_the_namespace
308
405
  #
@@ -320,10 +417,50 @@ class Base # === Open::Base
320
417
  end
321
418
 
322
419
  # ========================================================================= #
323
- # === namespace?
420
+ # === this_file_was_not_found
421
+ #
422
+ # Use this to notify the user, whenever the open-gem was unable to
423
+ # find a file that was assumed to exist locally.
324
424
  # ========================================================================= #
325
- def namespace?
326
- @namespace
425
+ def this_file_was_not_found(i)
426
+ e "#{rev}No file called `#{sfile(i)}#{rev}` was found. It "\
427
+ "is assumed to not exist."
428
+ end; alias no_file_exists_at this_file_was_not_found # === no_file_exists_at
429
+ alias no_file_was_found_at this_file_was_not_found # === no_file_was_found_at
430
+
431
+ # ========================================================================= #
432
+ # === esystem (esystem tag)
433
+ #
434
+ # This method contains a bit of an ad-hoc fix to make this work on
435
+ # windows as well.
436
+ #
437
+ # Eventually may have to rewrite the method a little bit, but for now
438
+ # (September 2021) this has to suffice.
439
+ # ========================================================================= #
440
+ def esystem(
441
+ i,
442
+ do_show_the_command_that_will_be_used = true # This is the default.
443
+ )
444
+ if is_on_windows?
445
+ # i = i.to_s.sub(/\\/,'\\') if i.include?("\\")
446
+ i = '"'+i.to_s+'"' if i.include?(' ')
447
+ end
448
+ e "#{rev}#{i}" if do_show_the_command_that_will_be_used
449
+ system(i)
450
+ end
451
+
452
+ # ========================================================================= #
453
+ # === rev
454
+ # ========================================================================= #
455
+ def rev
456
+ return ::Colours.rev if Object.const_defined? :Colours
457
+ return ''
327
458
  end
328
459
 
329
- end; end
460
+ end; end
461
+
462
+ if __FILE__ == $PROGRAM_NAME
463
+ alias e puts
464
+ base = Open::Base.new(ARGV)
465
+ e base.host_os?
466
+ end # base.rb
@@ -0,0 +1,8 @@
1
+ This directory is specifically to enable the functionality of
2
+ "opening books". Books in this context refers to PDF files,
3
+ that is, .pdf files. In order for this functionality to work,
4
+ you need to have .pdf files available locally, and you also
5
+ need to supply a custom file that keeps track of the themes
6
+ of the books, such as "all books that handle the theme
7
+ genetics". Then, once such a file has been made available,
8
+ class Open::Books will simply open all these books.
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === Open::Book
6
+ #
7
+ # This class will specifically open "books", that is, .pdf files.
8
+ #
9
+ # Usage example:
10
+ #
11
+ # Open::Book.new(ARGV)
12
+ #
13
+ # =========================================================================== #
14
+ require 'open/base/base.rb'
15
+
16
+ module Open
17
+
18
+ class Book < ::Open::Base # === Open::Book
19
+
20
+ # ========================================================================= #
21
+ # === FILE_TOPICS_PER_BOOK
22
+ # ========================================================================= #
23
+ FILE_TOPICS_PER_BOOK = '/home/x/books/topics_per_book.yml'
24
+
25
+ # ========================================================================= #
26
+ # === initialize
27
+ # ========================================================================= #
28
+ def initialize(
29
+ i = ARGV,
30
+ run_already = true
31
+ )
32
+ reset
33
+ set_commandline_arguments(i)
34
+ run if run_already
35
+ end
36
+
37
+ # ========================================================================= #
38
+ # === reset (reset tag)
39
+ # ========================================================================= #
40
+ def reset
41
+ super()
42
+ infer_the_namespace
43
+ # ======================================================================= #
44
+ # === @dataset
45
+ # ======================================================================= #
46
+ @dataset = nil
47
+ if File.exist?(FILE_TOPICS_PER_BOOK)
48
+ @dataset = YAML.load_file(FILE_TOPICS_PER_BOOK)
49
+ end
50
+ end
51
+
52
+ # ========================================================================= #
53
+ # === main_file?
54
+ # ========================================================================= #
55
+ def main_file?
56
+ FILE_TOPICS_PER_BOOK
57
+ end
58
+
59
+ # ========================================================================= #
60
+ # === open_these_files
61
+ # ========================================================================= #
62
+ def open_these_files(array)
63
+ require 'open/open/open.rb'
64
+ array.map! {|entry|
65
+ entry = entry.dup
66
+ unless entry.include?('/home/x/books/')
67
+ entry.prepend(
68
+ entry.delete_suffix('.pdf')+'/'
69
+ )
70
+ entry.prepend('/home/x/books/')
71
+ end
72
+ entry
73
+ }
74
+ ::Open::Open.new(array)
75
+ end
76
+
77
+ # ========================================================================= #
78
+ # === run (run tag)
79
+ # ========================================================================= #
80
+ def run
81
+ _ = @dataset
82
+ commandline_arguments?.each {|this_topic|
83
+ this_topic = this_topic.dup if this_topic.frozen?
84
+ this_topic.delete!(':') if this_topic.include? ':'
85
+ this_topic.downcase! # Keep it downcased at all times past this point.
86
+ if _.has_key?(this_topic)
87
+ opne 'Processing the topic '+steelblue(this_topic)+' next.'
88
+ open_these_files(_[this_topic])
89
+ else
90
+ opne 'The topic '+steelblue(this_topic)+' was not '\
91
+ 'found in the file '+main_file?+'.'
92
+ end
93
+ }
94
+ end
95
+
96
+ end; end
97
+
98
+ if __FILE__ == $PROGRAM_NAME
99
+ Open::Book.new(ARGV)
100
+ end # openbooks :java