open 0.1.23

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of open might be problematic. Click here for more details.

data/lib/open/open.rb ADDED
@@ -0,0 +1,1026 @@
1
+ #!/usr/bin/ruby -w
2
+ # Encoding: UTF-8
3
+ # frozen_string_literal: true
4
+ # =========================================================================== #
5
+ # === Open::Open
6
+ #
7
+ # This class will simply open a given file. It may also "open" the file
8
+ # in the browser, that is, to use primarily firefox to display the file
9
+ # content as such.
10
+ #
11
+ # Usage example:
12
+ #
13
+ # Open::Open.new(ARGV)
14
+ #
15
+ # =========================================================================== #
16
+ # require 'open/open.rb'
17
+ # Open::Open.new(ARGV)
18
+ # =========================================================================== #
19
+ require 'open/base/base.rb'
20
+
21
+ module Open
22
+
23
+ class Open < ::Open::Base # === Open::Open
24
+
25
+ require 'open/in_editor/in_editor.rb'
26
+ require 'open/in_browser/in_browser.rb'
27
+ require 'open/toplevel_code/toplevel_code.rb'
28
+
29
+ begin
30
+ require 'roebe/classes/find_expanded_alias.rb'
31
+ rescue LoadError; end
32
+
33
+ # ========================================================================= #
34
+ # === LIBREOFFICE
35
+ #
36
+ # A hardcoded path. This is no longer as important as it used to be,
37
+ # though. In the future, it may include an ENV value.
38
+ # ========================================================================= #
39
+ # LIBREOFFICE = '/usr/bin/soffice'
40
+ # LIBREOFFICE = '/opt/libreoffice/program/soffice'
41
+ if ENV['PATH_TO_THE_LIBREOFFICE_EXECUTABLE']
42
+ LIBREOFFICE = ENV['PATH_TO_THE_LIBREOFFICE_EXECUTABLE'].to_s.dup
43
+ else
44
+ LIBREOFFICE = '/usr/bin/soffice'
45
+ end
46
+
47
+ # ========================================================================= #
48
+ # === USE_THIS_MPLAYER_COMMAND
49
+ # ========================================================================= #
50
+ USE_THIS_MPLAYER_COMMAND =
51
+ 'mplayer -vo x11'
52
+
53
+ # ========================================================================= #
54
+ # === DELAY_IF_WE_HAVE_MORE_THAN_N_ENTRIES
55
+ # ========================================================================= #
56
+ DELAY_IF_WE_HAVE_MORE_THAN_N_ENTRIES = 4
57
+
58
+ # ========================================================================= #
59
+ # === USE_THIS_DELAY
60
+ #
61
+ # Sleep in n seconds before opening a file, if we have more
62
+ # entries than the above threshold value did define.
63
+ # ========================================================================= #
64
+ USE_THIS_DELAY = 0.65
65
+
66
+ # ========================================================================= #
67
+ # === ARRAY_EXTENSIONS_THAT_CAN_BE_OPENED_IN_THE_EDITOR
68
+ #
69
+ # All extensions that can be opened in the editor should be registered
70
+ # in this constant.
71
+ #
72
+ # For example, "h" means ".h" aka a C or C++ header file.
73
+ # ========================================================================= #
74
+ ARRAY_EXTENSIONS_THAT_CAN_BE_OPENED_IN_THE_EDITOR = %w(
75
+ php rb txt yaml yml cgi
76
+ md gemspec html csv py
77
+ conf c sh js log css cr
78
+ ascii la pl perl json
79
+ js fasta fa m3u cpp
80
+ go gff gff3
81
+ gen h
82
+ erb sinatra
83
+ sql
84
+ ).sort << '' # The last part is for files like "TODO" which lack an extension.
85
+
86
+ # ========================================================================= #
87
+ # === ARRAY_LIBREOFFICE_EXTENSIONS
88
+ #
89
+ # All libreoffice extensions will be stored here.
90
+ # ========================================================================= #
91
+ ARRAY_LIBREOFFICE_EXTENSIONS = %w(
92
+ xls
93
+ odt
94
+ doc
95
+ docx
96
+ ppt
97
+ xlsx
98
+ sxw
99
+ swx
100
+ rtf
101
+ ods
102
+ odp
103
+ pptx
104
+ pps
105
+ )
106
+
107
+ # ========================================================================= #
108
+ # === ARRAY_IMAGES
109
+ #
110
+ # All file-extensions for images can be registered in this Array.
111
+ # ========================================================================= #
112
+ ARRAY_IMAGES = %w(
113
+ png
114
+ jpg
115
+ gif
116
+ jpeg
117
+ tiff
118
+ tif
119
+ bmp
120
+ )
121
+
122
+ # ========================================================================= #
123
+ # === ARRAY_VIDEOS
124
+ # ========================================================================= #
125
+ ARRAY_VIDEOS = %w(
126
+ vob
127
+ avi
128
+ flv
129
+ mp3
130
+ mp4
131
+ )
132
+
133
+ # ========================================================================= #
134
+ # === initialize
135
+ # ========================================================================= #
136
+ def initialize(
137
+ i = nil,
138
+ run_already = true,
139
+ &block
140
+ )
141
+ reset
142
+ set_input(i)
143
+ # ======================================================================= #
144
+ # === Handle blocks next
145
+ # ======================================================================= #
146
+ if block_given?
147
+ yielded = yield
148
+ # ===================================================================== #
149
+ # === Handle hashes next
150
+ # ===================================================================== #
151
+ if yielded.is_a? Hash
152
+ # =================================================================== #
153
+ # === :use_this_editor
154
+ # =================================================================== #
155
+ if yielded.has_key? :use_this_editor
156
+ set_use_this_editor(yielded.delete(:use_this_editor))
157
+ end
158
+ # =================================================================== #
159
+ # === :open_via_fullscreen
160
+ # =================================================================== #
161
+ if yielded.has_key? :open_via_fullscreen
162
+ @open_via_fullscreen = yielded.delete(:open_via_fullscreen)
163
+ end
164
+ end
165
+ end
166
+ run if run_already
167
+ end
168
+
169
+ # ========================================================================= #
170
+ # === reset (reset tag)
171
+ # ========================================================================= #
172
+ def reset
173
+ super()
174
+ infer_the_namespace
175
+ # ======================================================================= #
176
+ # === @image_editor
177
+ # ======================================================================= #
178
+ @image_editor = 'gimp'
179
+ # ======================================================================= #
180
+ # === @editor
181
+ # ======================================================================= #
182
+ @editor = use_which_editor?
183
+ # ======================================================================= #
184
+ # === @set_the_main_book
185
+ # ======================================================================= #
186
+ @set_the_main_book = false
187
+ # ======================================================================= #
188
+ # === @open_via_fullscreen
189
+ # ======================================================================= #
190
+ @open_via_fullscreen = false
191
+ end
192
+
193
+ # ========================================================================= #
194
+ # === set_the_main_book?
195
+ # ========================================================================= #
196
+ def set_the_main_book?
197
+ @set_the_main_book
198
+ end
199
+
200
+ # ========================================================================= #
201
+ # === set_use_this_editor
202
+ # ========================================================================= #
203
+ def set_use_this_editor(
204
+ i = use_which_editor?
205
+ )
206
+ @editor = i.to_s
207
+ end
208
+
209
+ # ========================================================================= #
210
+ # === replace_localhost_with_data
211
+ # ========================================================================= #
212
+ def replace_localhost_with_data(i)
213
+ if i.include? 'programming'
214
+ return i.sub('localhost','/home/x/')
215
+ else
216
+ return i.sub('localhost','/home/x/data/')
217
+ end
218
+ end
219
+
220
+ # ========================================================================= #
221
+ # === set_input
222
+ # ========================================================================= #
223
+ def set_input(i = ARGV)
224
+ i = [i] unless i.is_a? Array
225
+ i.map! {|entry|
226
+ entry = entry.to_s.dup
227
+ # ===================================================================== #
228
+ # Split away at '::' if this is part of that substring.
229
+ # ===================================================================== #
230
+ if entry.include? '::'
231
+ splitted = entry.split('::')
232
+ entry = splitted.last
233
+ end
234
+ if entry.include? '^'
235
+ entry.delete!('^')
236
+ end
237
+ case entry
238
+ # ===================================================================== #
239
+ # === open --everything
240
+ #
241
+ # This actually refers only to files, so we select for files next.
242
+ # ===================================================================== #
243
+ when /^-?-?everything?$/i
244
+ entry = Dir['**/**'].select {|inner_entry| File.file?(inner_entry) }
245
+ # ===================================================================== #
246
+ # === open --important-exam
247
+ # ===================================================================== #
248
+ when /^-?-?important(-|_)?exams?$/i
249
+ base_dir = ENV['USERS']
250
+ base_dir = '/home' if base_dir.nil?
251
+ entry = "#{base_dir}/x/programming/ruby/src/studium/lib/studium/yaml/important_exams.yml"
252
+ end
253
+ # ===================================================================== #
254
+ # Get rid of localhost next. This must be handled with more care,
255
+ # because some files may include the string 'localhost' as part of
256
+ # their name, such as 'remove_localhost.rb'. In this case, we will
257
+ # additionally check whether the file exists.
258
+ # ===================================================================== #
259
+ if entry.is_a?(String) and entry.include?('localhost')
260
+ unless File.exist? entry # See the above header for an explanation.
261
+ entry = replace_localhost_with_data(entry)
262
+ end
263
+ end
264
+ if entry.is_a? String
265
+ entry.chop! if entry.end_with? '#' # Don't need trailing '#' tokens.
266
+ entry.chop! if entry.end_with? ':-' # <- This check must come before the check against ':'.
267
+ entry.chop! if entry.end_with? ':' # Chop off trailing ':' tokens.
268
+ # ===================================================================== #
269
+ # Next, we handle input such as:
270
+ # 'lib/lpc/requires/basic_requires.rb:begin'
271
+ # This evidently does not end with a ':' character, but it clearly
272
+ # has a fairly useless ':' component in it. If that is the case,
273
+ # we will treat this as input that is only valid up towards the
274
+ # very right ':', anchored on the '.rb:' part.
275
+ # ===================================================================== #
276
+ if entry.include? '.rb:'
277
+ # =================================================================== #
278
+ # The following code means to find the index at '.rb:' and then add
279
+ # 2 to it - this should be the correct name of the entry at hand.
280
+ # =================================================================== #
281
+ entry = entry[0 .. (entry.index('.rb:')+2)]
282
+ end
283
+ if entry.end_with?(',') and !File.exist?(',')
284
+ entry.chop!
285
+ elsif entry.end_with?('.') and File.exist?(entry[0..-2])
286
+ # =================================================================== #
287
+ # This clause will be entered if we have input something like
288
+ # "colours.rb." where the user may have wanted to type in
289
+ # "colours.rb" - and IF the file exists.
290
+ # =================================================================== #
291
+ opnn; e "Assuming a superfluous trailing '.', so removing "\
292
+ "the last '.' there."
293
+ entry.chop!
294
+ end
295
+ end
296
+ case entry # Work only on the first entry. (case tag)
297
+ # ===================================================================== #
298
+ # === open ME
299
+ # ===================================================================== #
300
+ when 'ME',
301
+ 'SELF',
302
+ 'ALL',/
303
+ ^-?-?this(_|-)?file/
304
+ open_this_file_here
305
+ exit
306
+ # ===================================================================== #
307
+ # === open --help
308
+ # ===================================================================== #
309
+ when /^-?-?help$/i,
310
+ 'show_help'
311
+ show_help
312
+ exit
313
+ end unless File.exist?(entry.to_s)
314
+ entry
315
+ }
316
+ @input = i # This must be an Array.
317
+ end; alias set_input_files set_input # === set_input_files
318
+
319
+ # ========================================================================= #
320
+ # === input?
321
+ # ========================================================================= #
322
+ def input?
323
+ @input
324
+ end; alias input_file? input? # === input_file?
325
+ alias input_files? input? # === input_files?
326
+
327
+ # ========================================================================= #
328
+ # === check_whether_the_user_has_provided_any_input
329
+ # ========================================================================= #
330
+ def check_whether_the_user_has_provided_any_input
331
+ _ = input_files?
332
+ local_files = Dir['*'].select {|entry| File.file? entry }
333
+ if _.empty? and !local_files.empty? and (local_files.size == 1)
334
+ # ===================================================================== #
335
+ # Handle the case where no specific input was given, but only
336
+ # one file exists in the local directory.
337
+ # ===================================================================== #
338
+ set_input_files(local_files.first)
339
+ _ = input_files?
340
+ end
341
+ if _.empty?
342
+ if is_on_roebe? and !is_bluefish_running?
343
+ start_bluefish
344
+ else
345
+ opnn; e 'Please provide at least one argument - the file '\
346
+ 'you wish to open.'
347
+ exit
348
+ end
349
+ end
350
+ end
351
+
352
+ # ========================================================================= #
353
+ # === start_bluefish
354
+ # ========================================================================= #
355
+ def start_bluefish
356
+ esystem 'bluefish &'
357
+ end
358
+
359
+ # ========================================================================= #
360
+ # === is_bluefish_running?
361
+ # ========================================================================= #
362
+ def is_bluefish_running?
363
+ `ps ax | grep bluefish`.split("\n").reject {|entry|
364
+ entry.include? 'grep'
365
+ }.size > 0
366
+ end
367
+
368
+ # ========================================================================= #
369
+ # === consider_padding
370
+ #
371
+ # Simply add a surrounding '"' to the given input, so that any resulting
372
+ # system() call will still work if we have awkward filenames.
373
+ # ========================================================================= #
374
+ def consider_padding(i)
375
+ if i.include?(' ') or i.include?('(')
376
+ i = '"'+i+'"'
377
+ end
378
+ return i
379
+ end
380
+
381
+ # ========================================================================= #
382
+ # === play_multimedia_file
383
+ # ========================================================================= #
384
+ def play_multimedia_file(i)
385
+ esystem "#{USE_THIS_MPLAYER_COMMAND} #{i}" # open
386
+ end
387
+
388
+ # ========================================================================= #
389
+ # === open_this_file_here
390
+ # ========================================================================= #
391
+ def open_this_file_here
392
+ do_open_in_editor(this_file?+IN_BACKGROUND)
393
+ end
394
+
395
+ # ========================================================================= #
396
+ # === return_this_file_here
397
+ # ========================================================================= #
398
+ def return_this_file_here
399
+ __FILE__
400
+ end; alias this_file? return_this_file_here # === this_file?
401
+
402
+ # ========================================================================= #
403
+ # === delay?
404
+ # ========================================================================= #
405
+ def delay?
406
+ USE_THIS_DELAY
407
+ end
408
+
409
+ # ========================================================================= #
410
+ # === find_and_return_last_file
411
+ # ========================================================================= #
412
+ def find_and_return_last_file
413
+ array = Dir['*'].reject {|entry| ! File.file? entry }
414
+ array.map! {|entry|
415
+ [entry, File.ctime(entry)]
416
+ }
417
+ result = array.sort_by {|entry| entry[1] }.reverse
418
+ result = result.first[0]
419
+ return result
420
+ end
421
+
422
+ # ========================================================================= #
423
+ # === can_be_opened_in_the_editor?
424
+ # ========================================================================= #
425
+ def can_be_opened_in_the_editor?(i)
426
+ _ = File.extname(i).delete('.')
427
+ ARRAY_EXTENSIONS_THAT_CAN_BE_OPENED_IN_THE_EDITOR.include? i
428
+ end
429
+
430
+ # ========================================================================= #
431
+ # === try_to_open_this_file_in_the_editor
432
+ # ========================================================================= #
433
+ def try_to_open_this_file_in_the_editor(
434
+ i = input_files?
435
+ )
436
+ # ======================================================================= #
437
+ # === First check whether we have passed an Array
438
+ # ======================================================================= #
439
+ if i.is_a? Array # Array tag
440
+ if i.size > DELAY_IF_WE_HAVE_MORE_THAN_N_ENTRIES
441
+ opnn; e 'More than '+simp(DELAY_IF_WE_HAVE_MORE_THAN_N_ENTRIES.to_s)+
442
+ ' entries given ('+i.size.to_s+'), hence we will use a '\
443
+ 'small delay (of '+sfancy(delay?.to_s)+' seconds).'
444
+ end
445
+ i.each {|entry|
446
+ sleep delay? if i.size > DELAY_IF_WE_HAVE_MORE_THAN_N_ENTRIES # Small delay.
447
+ try_to_open_this_file_in_the_editor(entry)
448
+ }
449
+ else
450
+ # ===================================================================== #
451
+ # Get rid of localhost-string parts next.
452
+ # ===================================================================== #
453
+ if i.include? 'localhost'
454
+ i = replace_localhost_with_data(i)
455
+ end unless File.exist? i
456
+ # ===================================================================== #
457
+ # Next, we chop off '?' characters. This is, however had, not good if
458
+ # this is part of the filename. So we must check if the file exists,
459
+ # prior to doing this check.
460
+ # ===================================================================== #
461
+ unless File.exist? i
462
+ i = i[0..i.index('?')] if i.include? '?'
463
+ end
464
+ # ===================================================================== #
465
+ # Get rid of '#' in the input, if it exists.
466
+ # ===================================================================== #
467
+ i = i[0..i.index('#')] if i.include? '#'
468
+ case i
469
+ when 'LAST' # Assign the last file.
470
+ i = find_and_return_last_file
471
+ end
472
+ # ===================================================================== #
473
+ # Next, act on the extension name.
474
+ # ===================================================================== #
475
+ _ = File.extname(i).delete('.').downcase
476
+ case _ # case tag
477
+ # ===================================================================== #
478
+ # === open .pdf files
479
+ # ===================================================================== #
480
+ when 'pdf'
481
+ open_in_pdf_viewer(i)
482
+ # ===================================================================== #
483
+ # === epub
484
+ # ===================================================================== #
485
+ when 'epub'
486
+ esystem "okular #{i} &"
487
+ # ===================================================================== #
488
+ # === torrent
489
+ # ===================================================================== #
490
+ when 'torrent'
491
+ open_this_torrent_file(i)
492
+ # ===================================================================== #
493
+ # === Extensions that can be opened in the editor
494
+ # ===================================================================== #
495
+ when *ARRAY_EXTENSIONS_THAT_CAN_BE_OPENED_IN_THE_EDITOR
496
+ open_in_browser_or_in_editor(i)
497
+ # ===================================================================== #
498
+ # === All registered images
499
+ # ===================================================================== #
500
+ when *ARRAY_IMAGES
501
+ open_in_gimp(i)
502
+ # ===================================================================== #
503
+ # === All libreoffice extensions
504
+ # ===================================================================== #
505
+ when *ARRAY_LIBREOFFICE_EXTENSIONS
506
+ open_in_office(i)
507
+ # ===================================================================== #
508
+ # === All videos
509
+ # ===================================================================== #
510
+ when *ARRAY_VIDEOS
511
+ play_multimedia_file(i)
512
+ else
513
+ if File.exist? i
514
+ opnn; e "Not registered extension `#{sfancy(_)}`."
515
+ opnn; e 'We will attempt to open it anyway though.'
516
+ open_in_browser_or_in_editor(i)
517
+ else # else we conclude that the file does not exist.
518
+ no_file_was_found_at(i)
519
+ end
520
+ end
521
+ end
522
+ end; alias consider_opening_the_given_input try_to_open_this_file_in_the_editor # === consider_opening_the_given_input
523
+ alias open_in_editor try_to_open_this_file_in_the_editor # === open_in_editor
524
+ alias open_these_files try_to_open_this_file_in_the_editor # === open_these_files
525
+
526
+ # ========================================================================= #
527
+ # === open_this_torrent_file
528
+ # ========================================================================= #
529
+ def open_this_torrent_file(i)
530
+ if i.include?("'") and !i.include?('"')
531
+ i = '"'+i+'"'
532
+ end
533
+ _ = "transmission #{i} &"
534
+ esystem(_)
535
+ end
536
+
537
+ # ========================================================================= #
538
+ # === try_to_find_files_based_on_hyphens_as_part_of_the_input
539
+ #
540
+ # This method will try to find files based on '::' input.'
541
+ # ========================================================================= #
542
+ def try_to_find_files_based_on_hyphens_as_part_of_the_input(i)
543
+ if i.include? '::'
544
+ # ===================================================================== #
545
+ # In this case, replace '::', after passing it through the
546
+ # snakecase() method.
547
+ # ===================================================================== #
548
+ i = snakecase_and_prepend_first_name_and_lib(i).tr('::','/')+'/'
549
+ end
550
+ unless i.start_with?('/home')
551
+ # ===================================================================== #
552
+ # We assume that only ruby files follow the '::' layout, for now. (Jun 2017)
553
+ # ===================================================================== #
554
+ i.prepend('$RUBY_SRC/')
555
+ end
556
+ if i.include? '$'
557
+ i = convert_global_env(i)
558
+ end
559
+ i.squeeze!('/')
560
+ unless i.end_with?('*')
561
+ i << '*'
562
+ end
563
+ these_files = Dir[i]
564
+ open_these_files(these_files)
565
+ end
566
+
567
+ # ========================================================================= #
568
+ # === snakecase_and_prepend_first_name_and_lib
569
+ #
570
+ # This combines snakecase() by also prepending the first-name
571
+ # and "lib/" prefix.
572
+ # ========================================================================= #
573
+ def snakecase_and_prepend_first_name_and_lib(i)
574
+ if i.include? '::'
575
+ splitted = i.split('::')
576
+ first_name = splitted.first.downcase
577
+ end
578
+ i = snakecase(i)
579
+ return first_name+'/lib/'+i
580
+ end
581
+
582
+ # ========================================================================= #
583
+ # === register_this_pdf_file
584
+ # ========================================================================= #
585
+ def register_this_pdf_file(what)
586
+ begin
587
+ require 'save_file'
588
+ require 'roebe/constants/file_constants.rb'
589
+ require 'roebe/constants/directory_constants.rb'
590
+ rescue LoadError; end
591
+ into = Roebe.file_these_pdf_files_were_opened
592
+ old_dataset = nil
593
+ if File.exist? into
594
+ # ===================================================================== #
595
+ # Sanitize this .yml file, in that case.
596
+ # ===================================================================== #
597
+ old_dataset = YAML.load_file(into).uniq
598
+ this_content = old_dataset.map {|entry| entry.prepend(' - ') }.join("\n")
599
+ SaveFile.write_what_into(this_content, into)
600
+ end
601
+ _ = Roebe.log_directory?
602
+ mkdir(_) unless File.directory? _
603
+ if old_dataset and old_dataset.map {|entry|
604
+ # =================================================================== #
605
+ # ensure_main_encoding is necessary to avoid illegal byte sequences.
606
+ # =================================================================== #
607
+ # ensure_main_encoding(entry).strip.delete('-').strip
608
+ # ^^^ Disabled as of September 2021. Let's see if we really need it still.
609
+ entry.strip.delete('-').strip
610
+ }.include? what
611
+ # ===================================================================== #
612
+ # In this case, we will remove the old entries, and then append.
613
+ # ===================================================================== #
614
+ old_dataset = YAML.load_file(into).uniq.reject {|entry|
615
+ # entry = ensure_main_encoding(entry) # Need to use a consistent encoding here.
616
+ # ^^^ Disabled as of September 2021.
617
+ entry.include? what
618
+ }
619
+ this_content = old_dataset.map {|entry|
620
+ entry.prepend(' - ')
621
+ }.join("\n")
622
+ SaveFile.write_what_into(this_content, into)
623
+ end
624
+ what = "\n - #{what}"
625
+ touch(into) unless File.exist? into
626
+ SaveFile.append_what_into(what, into) # Silently store that.
627
+ end
628
+
629
+ # ========================================================================= #
630
+ # === open_in_browser_or_in_editor
631
+ #
632
+ # This method was required because sometimes we wish to open in the
633
+ # browser, and sometimes we wish to open in the editor.
634
+ # ========================================================================= #
635
+ def open_in_browser_or_in_editor(i)
636
+ if i.include? '//'
637
+ i = i.dup if i.frozen?
638
+ i.squeeze!('/')
639
+ end
640
+ # ======================================================================= #
641
+ # Next, we get the extension name.
642
+ # ======================================================================= #
643
+ _ = File.extname(File.basename(i)).delete '.'
644
+ case _
645
+ when 'html','php' # Open in both, in this case.
646
+ do_open_in_editor(i)
647
+ unless File.zero? i
648
+ ::Open.in_browser(i) unless _.include? 'php'
649
+ end
650
+ else
651
+ do_open_in_editor(i)
652
+ end
653
+ end
654
+
655
+ # ========================================================================= #
656
+ # === open_in_gimp
657
+ # ========================================================================= #
658
+ def open_in_gimp(i)
659
+ esystem "#{@image_editor} #{i}#{IN_BACKGROUND}"
660
+ end
661
+
662
+ # ========================================================================= #
663
+ # === open_in_office
664
+ #
665
+ # This method should be used to open files that do have a file extension
666
+ # such as .xls or .odt or .ppt. In other words, libreoffice-specifi files.
667
+ # ========================================================================= #
668
+ def open_in_office(i)
669
+ i = consider_padding(i)
670
+ if File.exist? LIBREOFFICE
671
+ result = "#{LIBREOFFICE} #{i}#{IN_BACKGROUND}"
672
+ else # Try any other general location based on $PATH anyway.
673
+ result = File.basename(LIBREOFFICE)+' '+i+IN_BACKGROUND
674
+ end
675
+ esystem result
676
+ end
677
+
678
+ # ========================================================================= #
679
+ # === try_to_require_the_studium_project
680
+ # ========================================================================= #
681
+ def try_to_require_the_studium_project
682
+ unless Object.const_defined?(:Studium) and
683
+ Studium.respond_to?(:include_this_exam_topic?)
684
+ begin # We pull in only the relevant files from the Studium project.
685
+ require 'studium/constants/constants.rb'
686
+ require 'studium/toplevel_methods/find_exam_topic_and_exam_title.rb'
687
+ require 'studium/toplevel_methods/is_this_exam_topic_included.rb'
688
+ rescue LoadError
689
+ if is_on_roebe?
690
+ e 'The three files ('\
691
+ 'studium/constants/constants.rb,'\
692
+ 'studium/toplevel_methods/find_exam_topic_and_exam_title.rb and '\
693
+ 'studium/toplevel_methods/is_this_exam_topic_included.rb '\
694
+ 'forth) from the studium-project could not be loaded.'
695
+ end
696
+ end
697
+ end
698
+ end
699
+
700
+ # ========================================================================= #
701
+ # === do_open_in_editor
702
+ #
703
+ # This method will try to open the file via the specified (main)
704
+ # editor. Since as of August 2019, this will also be logged into
705
+ # a local file, if we are on a roebe-system.
706
+ # ========================================================================= #
707
+ def do_open_in_editor(
708
+ i, use_this_editor = @editor
709
+ )
710
+ if i.include? '//'
711
+ i.squeeze!('/')
712
+ end
713
+ if Object.const_defined? :Roebe
714
+ expanded_alias = Roebe::FindExpandedAlias.new(i) { :be_quiet }
715
+ if expanded_alias.is_included?
716
+ unless File.exist? i
717
+ points_at = expanded_alias.points_at?
718
+ opnn; e 'Making use of the aliased-pointer at'
719
+ opnn; e '`'+steelblue(points_at)+'`.'
720
+ i = points_at
721
+ end
722
+ end
723
+ end
724
+ i = rds(i) # Get rid of // again, just in case.
725
+ # ======================================================================= #
726
+ # Make an exception for .cpp files:
727
+ # ======================================================================= #
728
+ if (File.extname(i).delete('.') == 'cpp')
729
+ if is_on_roebe? and ENV.has_key?('CPP_EDITOR')
730
+ use_this_editor = ENV['CPP_EDITOR'].to_s.dup
731
+ else
732
+ use_this_editor = 'geany' # We use geany for cpp files.
733
+ end
734
+ end
735
+ if i.include?("'") and !i.include?('"')
736
+ i = '"'+i+'"'
737
+ end
738
+ if i.include? '('
739
+ i = '"'+i+'"'
740
+ end
741
+ _ = "#{use_this_editor} #{i}"
742
+ esystem(_)
743
+ if File.file?(i) and Object.const_defined?(:Roebe) and
744
+ File.directory?(Roebe.log_dir?) and
745
+ is_on_roebe?
746
+ into = Roebe.log_dir?+'opened_files.yml'
747
+ if File.exist? into
748
+ array = YAML.load_file(into)
749
+ else
750
+ array = [into].flatten.compact
751
+ end
752
+ what = YAML.dump(array)
753
+ SaveFile.write_what_into(what, into)
754
+ end
755
+ end
756
+
757
+ # ========================================================================= #
758
+ # === run_rcfiles_then_run_ata_via_qdbus
759
+ # ========================================================================= #
760
+ def run_rcfiles_then_run_ata_via_qdbus
761
+ require 'rcfiles'
762
+ Rcfiles.run
763
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/2 runCommand "ata"'
764
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/3 runCommand "ata"'
765
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/4 runCommand "ata"'
766
+ end
767
+
768
+ # ========================================================================= #
769
+ # === open_in_pdf_viewer (pdf tag)
770
+ #
771
+ # This method can be used to open a .pdf file. We will let the project
772
+ # PdfParadise handle this situation.
773
+ #
774
+ # Since as of 19.09.2018 we will keep a log of the opened .pdf files
775
+ # if we are on roebe. This can then be used to determine which were
776
+ # the last .pdf files that were read.
777
+ # ========================================================================= #
778
+ def open_in_pdf_viewer(i)
779
+ require 'pdf_paradise' unless Object.const_defined? :PdfParadise
780
+ # ======================================================================= #
781
+ # Since as of April 2022 we will use the absolute path to the .pdf
782
+ # file at hand. The reason for this is because this makes it easier
783
+ # to know which files are open, and we can store these file paths
784
+ # into a local file (such as a .yml file), and then use this at a
785
+ # later time to restore all .pdf files that were open. This thus
786
+ # constitutes some type of "session management".
787
+ # ======================================================================= #
788
+ i = File.absolute_path(i)
789
+ if File.exist? i
790
+ require 'pdf_paradise/main_pdf/main_pdf.rb'
791
+ require 'pdf_paradise/set_main_book.rb'
792
+ # ===================================================================== #
793
+ # Only enable the following on my home-system, and only in the
794
+ # books-subdirectory, and university-subdirectory.
795
+ # ===================================================================== #
796
+ if is_on_roebe? and set_the_main_book?
797
+ case return_pwd
798
+ # =================================================================== #
799
+ # The following checks were explained above. We will also run
800
+ # rcfiles, and send pidof.
801
+ # =================================================================== #
802
+ when /^#{Regexp.quote('/home/x/books/')}/,
803
+ /^#{Regexp.quote('/home/x/studium/')}/
804
+ PdfParadise::SetMainBook.new(i)
805
+ run_rcfiles_then_run_ata_via_qdbus
806
+ end
807
+ end
808
+ PdfParadise.main_pdf(i) {{
809
+ open_via_fullscreen: @open_via_fullscreen
810
+ }}
811
+ register_this_pdf_file(i)
812
+ else
813
+ this_file_was_not_found(i)
814
+ end
815
+ end
816
+
817
+ # ========================================================================= #
818
+ # === run_everything
819
+ # ========================================================================= #
820
+ def run_everything
821
+ input_files = input_files?.flatten
822
+ # ======================================================================= #
823
+ # Iterate over all input files that were passed to us.
824
+ # ======================================================================= #
825
+ input_files.each {|this_file|
826
+ if this_file.include?(':') and !File.exist?(this_file) and
827
+ File.exist?(this_file.split(':').first.to_s)
828
+ this_file = this_file.split(':').first.to_s
829
+ end
830
+ if this_file.start_with?('http:') and !File.exist?(this_file)
831
+ this_file.delete_prefix!('http:')
832
+ end
833
+ # ===================================================================== #
834
+ # === Query whether the file exists or whether it does not
835
+ # ===================================================================== #
836
+ if File.exist? this_file # This is the simplest way - the file exists here.
837
+ try_to_open_this_file_in_the_editor(this_file)
838
+ else # Ok, the file was not instantly found. Run more checks here.
839
+ possible_matches = Dir[('*'+this_file+'*').squeeze('*')] # <- This may be an empty Array as well.
840
+ # =================================================================== #
841
+ # Since as of Jan 2018, if the variable possible_matches is NOT
842
+ # empty, we will sort it in a way so that the shorter file names
843
+ # are on top of the array.
844
+ # =================================================================== #
845
+ unless possible_matches.empty?
846
+ possible_matches = possible_matches.sort_by {|entry| entry.size }
847
+ end
848
+ # =================================================================== #
849
+ # === Check whether the input is an exam-question next
850
+ #
851
+ # This check should come before we delegate towards FindExpandedAlias.
852
+ # =================================================================== #
853
+ if Object.const_defined?(:Studium) and
854
+ ::Studium.respond_to?(:include_this_exam_topic?) and
855
+ ::Studium.respond_to?(:find_corresponding_exam_topic) and
856
+ ::Studium.include_this_exam_topic?(this_file) # open ab2
857
+ _ = ::Studium.find_corresponding_exam_topic(
858
+ ::Studium.find_corresponding_exam_topic(this_file),
859
+ :be_quiet
860
+ ) # This can be false.
861
+ if _
862
+ if is_on_roebe?
863
+ _ = Studium.my_exam_topics_directory?+File.basename(_)
864
+ else
865
+ _ = Studium.exam_topics_directory?+File.basename(_)
866
+ end
867
+ open_in_editor(_)
868
+ end
869
+ # =================================================================== #
870
+ # === Query whether BeautifulUrl includes this file.
871
+ # =================================================================== #
872
+ elsif BeautifulUrl.does_include?(this_file) # open linux
873
+ _ = beautiful_url(this_file)
874
+ consider_opening_the_given_input(_) # Then try again.
875
+ # =================================================================== #
876
+ # Ok, the following else-clauses handle the situation
877
+ # that the given input could not be found.
878
+ # =================================================================== #
879
+ elsif this_file.include? 'project_'
880
+ do_open_in_editor(this_file)
881
+ # =================================================================== #
882
+ # At the least one entry has been found.
883
+ # =================================================================== #
884
+ elsif ((_ = possible_matches).size > 0) # If we can find at least one entry.
885
+ consider_opening_the_given_input(_.first) # Recursive call.
886
+ # =================================================================== #
887
+ # Same as above, but both prepend and append a '*' character.
888
+ # =================================================================== #
889
+ elsif ((_ = possible_matches).size > 0) # If we can find at least one entry.
890
+ consider_opening_the_given_input(_.first)
891
+ # =================================================================== #
892
+ # Next, try to pass it through class Roebe::FindExpandedAlias.
893
+ # =================================================================== #
894
+ elsif File.exist?(_ = Roebe.find_expanded_alias(this_file).to_s)
895
+ open_in_editor(_)
896
+ # =================================================================== #
897
+ # Next, try to handle input containing two ':' tokens.
898
+ # =================================================================== #
899
+ elsif this_file.include?('::')
900
+ try_to_find_files_based_on_hyphens_as_part_of_the_input(this_file)
901
+ # =================================================================== #
902
+ # Use RUBY_SRC as shortcut on my home system.
903
+ # =================================================================== #
904
+ elsif is_on_roebe? and
905
+ File.exist?(return_assumed_path_to_ruby_src_lib_of(this_file))
906
+ use_this_file_instead = return_assumed_path_to_ruby_src_lib_of(this_file)
907
+ e rev+'Since we are on roebe, we will use another path, aka'
908
+ e
909
+ e " #{steelblue(use_this_file_instead)}"
910
+ e
911
+ open_in_editor(use_this_file_instead)
912
+ # =================================================================== #
913
+ # === Check for aliases next
914
+ #
915
+ # Next, try to find an expanded alias here.
916
+ # =================================================================== #
917
+ elsif Roebe.const_defined?(:FindExpandedAlias) and
918
+ (::Roebe::FindExpandedAlias[this_file] != this_file)
919
+ do_open_in_editor(this_file)
920
+ else
921
+ opnn; e 'No match could be found for `'+sfancy(this_file)+'`.'
922
+ end
923
+ end
924
+ }
925
+ end
926
+
927
+ # ========================================================================= #
928
+ # === return_assumed_path_to_ruby_src_lib_of
929
+ #
930
+ # Input to this method should be a String like:
931
+ #
932
+ # roebe/classes/kde/kde_konsole/kde_konsole.rb
933
+ #
934
+ # ========================================================================= #
935
+ def return_assumed_path_to_ruby_src_lib_of(this_file)
936
+ first_part = File.dirname(this_file)
937
+ if first_part.include? '/'
938
+ first_part = first_part.split('/').first
939
+ end
940
+ return "#{RUBY_SRC}#{first_part}/lib/#{this_file}"
941
+ end
942
+
943
+ # ========================================================================= #
944
+ # === show_help (help tag)
945
+ # ========================================================================= #
946
+ def show_help
947
+ opnn; e 'The following options are available:'
948
+ e
949
+ ecomment ' SELF # Open this .rb file here.'
950
+ ecomment ' --use-this-browser=firefox # Assign a new browser, in this case firefox.'
951
+ e
952
+ end
953
+
954
+ # ========================================================================= #
955
+ # === run (run tag)
956
+ # ========================================================================= #
957
+ def run
958
+ check_whether_the_user_has_provided_any_input
959
+ try_to_require_the_studium_project
960
+ try_to_require_the_beautiful_url_project
961
+ menu
962
+ run_everything
963
+ end
964
+
965
+ # ========================================================================= #
966
+ # === menu (menu tag)
967
+ # ========================================================================= #
968
+ def menu(
969
+ i = input?
970
+ )
971
+ if i.is_a? Array
972
+ i.each {|entry| menu(entry) }
973
+ else
974
+ case i # (case tag)
975
+ # ===================================================================== #
976
+ # === open --use-this-browser=firefox
977
+ # ===================================================================== #
978
+ when /^-?-?use(-|_)?this(-|_)?browser=(.+)/
979
+ ::Open.permanently_use_this_browser = $3.to_s.dup
980
+ exit
981
+ end
982
+ end
983
+ end
984
+
985
+ # ========================================================================= #
986
+ # === try_to_require_the_beautiful_url_project
987
+ # ========================================================================= #
988
+ def try_to_require_the_beautiful_url_project
989
+ unless Object.const_defined? :BeautifulUrl
990
+ begin
991
+ require 'roebe/requires/failsafe_require_of_beautiful_url.rb'
992
+ rescue LoadError; end
993
+ end
994
+ end
995
+
996
+ # ========================================================================= #
997
+ # === Open::Open[]
998
+ # ========================================================================= #
999
+ def self.[](i = ARGV, &block)
1000
+ new(i, &block)
1001
+ end
1002
+
1003
+ end
1004
+
1005
+ # =========================================================================== #
1006
+ # === Open.open
1007
+ # =========================================================================== #
1008
+ def self.open(i = ARGV, &block)
1009
+ ::Open::Open.new(i, &block)
1010
+ end
1011
+
1012
+ # =========================================================================== #
1013
+ # === Open.pdf_viewer?
1014
+ # =========================================================================== #
1015
+ def self.pdf_viewer?
1016
+ unless (Object.const_defined?(:PdfParadise) and PdfParadise.const_defined?(:MainPdf))
1017
+ require 'pdf_paradise/main_pdf/main_pdf.rb'
1018
+ end
1019
+ return ::PdfParadise.use_which_pdf_viewer?
1020
+ end
1021
+
1022
+ end
1023
+
1024
+ if __FILE__ == $PROGRAM_NAME
1025
+ Open::Open.new(ARGV)
1026
+ end # open