open 0.1.30

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.
data/lib/open/open.rb ADDED
@@ -0,0 +1,1057 @@
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
+ if points_at.include?(';')
719
+ splitted = points_at.split(';')
720
+ if File.exist? splitted.first
721
+ points_at = splitted.first
722
+ end
723
+ end
724
+ opnn; e 'Making use of the aliased-pointer at'
725
+ opnn; e ' `'+steelblue(points_at)+'`.'
726
+ i = points_at
727
+ end
728
+ end
729
+ end
730
+ i = rds(i) # Get rid of // again, just in case.
731
+ # ======================================================================= #
732
+ # Make an exception for .cpp files:
733
+ # ======================================================================= #
734
+ if (File.extname(i).delete('.') == 'cpp')
735
+ if is_on_roebe? and ENV.has_key?('CPP_EDITOR')
736
+ use_this_editor = ENV['CPP_EDITOR'].to_s.dup
737
+ else
738
+ use_this_editor = 'geany' # We use geany for cpp files.
739
+ end
740
+ end
741
+ if i.include?("'") and !i.include?('"')
742
+ i = '"'+i+'"'
743
+ end
744
+ if i.include? '('
745
+ i = '"'+i+'"'
746
+ end
747
+ _ = "#{use_this_editor} #{i}"
748
+ esystem(_)
749
+ if File.file?(i) and Object.const_defined?(:Roebe) and
750
+ File.directory?(Roebe.log_dir?) and
751
+ is_on_roebe?
752
+ into = Roebe.log_dir?+'opened_files.yml'
753
+ if File.exist? into
754
+ array = YAML.load_file(into)
755
+ else
756
+ array = [into].flatten.compact
757
+ end
758
+ what = YAML.dump(array)
759
+ SaveFile.write_what_into(what, into)
760
+ end
761
+ end
762
+
763
+ # ========================================================================= #
764
+ # === run_rcfiles_then_run_ata_via_qdbus
765
+ # ========================================================================= #
766
+ def run_rcfiles_then_run_ata_via_qdbus
767
+ require 'rcfiles'
768
+ Rcfiles.run
769
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/2 runCommand "ata"'
770
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/3 runCommand "ata"'
771
+ esystem 'qdbus org.kde.konsole-`pidof -s konsole` /Sessions/4 runCommand "ata"'
772
+ end
773
+
774
+ # ========================================================================= #
775
+ # === open_in_pdf_viewer (pdf tag)
776
+ #
777
+ # This method can be used to open a .pdf file. We will let the project
778
+ # PdfParadise handle this situation.
779
+ #
780
+ # Since as of 19.09.2018 we will keep a log of the opened .pdf files
781
+ # if we are on roebe. This can then be used to determine which were
782
+ # the last .pdf files that were read.
783
+ # ========================================================================= #
784
+ def open_in_pdf_viewer(i)
785
+ require 'pdf_paradise' unless Object.const_defined? :PdfParadise
786
+ # ======================================================================= #
787
+ # Since as of April 2022 we will use the absolute path to the .pdf
788
+ # file at hand. The reason for this is because this makes it easier
789
+ # to know which files are open, and we can store these file paths
790
+ # into a local file (such as a .yml file), and then use this at a
791
+ # later time to restore all .pdf files that were open. This thus
792
+ # constitutes some type of "session management".
793
+ # ======================================================================= #
794
+ i = File.absolute_path(i)
795
+ if File.exist? i
796
+ require 'pdf_paradise/main_pdf/main_pdf.rb'
797
+ require 'pdf_paradise/set_main_book.rb'
798
+ # ===================================================================== #
799
+ # Only enable the following on my home-system, and only in the
800
+ # books-subdirectory, and university-subdirectory.
801
+ # ===================================================================== #
802
+ if is_on_roebe? and set_the_main_book?
803
+ case return_pwd
804
+ # =================================================================== #
805
+ # The following checks were explained above. We will also run
806
+ # rcfiles, and send pidof.
807
+ # =================================================================== #
808
+ when /^#{Regexp.quote('/home/x/books/')}/,
809
+ /^#{Regexp.quote('/home/x/studium/')}/
810
+ PdfParadise::SetMainBook.new(i)
811
+ run_rcfiles_then_run_ata_via_qdbus
812
+ end
813
+ end
814
+ PdfParadise.main_pdf(i) {{
815
+ open_via_fullscreen: @open_via_fullscreen
816
+ }}
817
+ register_this_pdf_file(i)
818
+ else
819
+ this_file_was_not_found(i)
820
+ end
821
+ end
822
+
823
+ # ========================================================================= #
824
+ # === return_assumed_path_to_ruby_src_lib_of
825
+ #
826
+ # Input to this method should be a String like:
827
+ #
828
+ # roebe/classes/kde/kde_konsole/kde_konsole.rb
829
+ #
830
+ # ========================================================================= #
831
+ def return_assumed_path_to_ruby_src_lib_of(this_file)
832
+ first_part = File.dirname(this_file)
833
+ if first_part.include? '/'
834
+ first_part = first_part.split('/').first
835
+ end
836
+ return "#{RUBY_SRC}#{first_part}/lib/#{this_file}"
837
+ end
838
+
839
+ # ========================================================================= #
840
+ # === show_help (help tag)
841
+ # ========================================================================= #
842
+ def show_help
843
+ opnn; e 'The following options are available:'
844
+ e
845
+ ecomment ' SELF # Open this .rb file here.'
846
+ ecomment ' --use-this-browser=firefox # Assign a new browser, in this case firefox.'
847
+ ecomment ' --browser? # '\
848
+ 'Show which browser is the currently assigned one.'
849
+ e
850
+ end
851
+
852
+ # ========================================================================= #
853
+ # === menu (menu tag)
854
+ # ========================================================================= #
855
+ def menu(
856
+ i = input?
857
+ )
858
+ if i.is_a? Array
859
+ i.each {|entry| menu(entry) }
860
+ else
861
+ case i # (case tag)
862
+ # ===================================================================== #
863
+ # === open --browser?
864
+ # ===================================================================== #
865
+ when /^-?-?browser\??$/
866
+ _ = YAML.load_file(::Open.file_browser?)
867
+ e 'The browser currently in use is `'+sfancy(_)+'`.'
868
+ exit
869
+ # ===================================================================== #
870
+ # === open --use-this-browser=firefox
871
+ # ===================================================================== #
872
+ when /^-?-?use(-|_)?this(-|_)?browser=(.+)/
873
+ ::Open.permanently_use_this_browser = $3.to_s.dup
874
+ exit
875
+ end
876
+ end
877
+ end
878
+
879
+ # ========================================================================= #
880
+ # === try_to_require_the_beautiful_url_project
881
+ # ========================================================================= #
882
+ def try_to_require_the_beautiful_url_project
883
+ unless Object.const_defined? :BeautifulUrl
884
+ begin
885
+ require 'roebe/requires/failsafe_require_of_beautiful_url.rb'
886
+ rescue LoadError; end
887
+ end
888
+ end
889
+
890
+ # ========================================================================= #
891
+ # === run_everything
892
+ # ========================================================================= #
893
+ def run_everything
894
+ input_files = input_files?.flatten
895
+ # ======================================================================= #
896
+ # Iterate over all input files that were passed to us.
897
+ # ======================================================================= #
898
+ input_files.each {|this_file|
899
+ # ===================================================================== #
900
+ # Check whether the input includes the ':' character:
901
+ # ===================================================================== #
902
+ if this_file.include?(':') and !File.exist?(this_file) and
903
+ File.exist?(this_file.split(':').first.to_s)
904
+ this_file = this_file.split(':').first.to_s
905
+ end
906
+ if this_file.start_with?('http:') and !File.exist?(this_file)
907
+ this_file.delete_prefix!('http:')
908
+ end
909
+ # ===================================================================== #
910
+ # === Query whether the file exists or whether it does not
911
+ # ===================================================================== #
912
+ if File.exist?(this_file) # This is the simplest way - the file exists here.
913
+ # =================================================================== #
914
+ # However had, in December 2022 it was noticed that a file such
915
+ # as "curricula.yml" may exist, as well as a directory called
916
+ # "curricula/". Thus, we may input "curricula" and refer to
917
+ # curricula.yml rather than curricula/. So, what to do in this
918
+ # case? Well - we will do a minimal glob, that is, if a file
919
+ # exists as described above, then we will prioritize this over
920
+ # the directory name.
921
+ # =================================================================== #
922
+ if File.directory?(this_file) and !File.file?(this_file) and
923
+ (Dir[this_file+'*'].size > 0)
924
+ this_file = Dir[this_file+'.*'].first.to_s # Pick a real file in this case.
925
+ end
926
+ try_to_open_this_file_in_the_editor(this_file)
927
+ else # Ok, the file was not instantly found. Run more checks here.
928
+ possible_matches = Dir[('*'+this_file+'*').squeeze('*')] # ← This may be an empty Array as well.
929
+ # =================================================================== #
930
+ # Since as of Jan 2018, if the variable possible_matches is NOT
931
+ # empty, we will sort it in a way so that the shorter file names
932
+ # are on top of the array.
933
+ # =================================================================== #
934
+ unless possible_matches.empty?
935
+ possible_matches = possible_matches.sort_by {|entry| entry.size }
936
+ end
937
+ # =================================================================== #
938
+ # === Check whether the input is an exam-question next
939
+ #
940
+ # This check should come before we delegate towards FindExpandedAlias.
941
+ # =================================================================== #
942
+ if Object.const_defined?(:Studium) and
943
+ ::Studium.respond_to?(:include_this_exam_topic?) and
944
+ ::Studium.respond_to?(:find_corresponding_exam_topic) and
945
+ ::Studium.include_this_exam_topic?(this_file) # open ab2
946
+ _ = ::Studium.find_corresponding_exam_topic(
947
+ ::Studium.find_corresponding_exam_topic(this_file),
948
+ :be_quiet
949
+ ) # This can be false.
950
+ if _
951
+ if is_on_roebe?
952
+ _ = Studium.my_exam_topics_directory?+File.basename(_)
953
+ else
954
+ _ = Studium.exam_topics_directory?+File.basename(_)
955
+ end
956
+ open_in_editor(_)
957
+ end
958
+ # =================================================================== #
959
+ # === Query whether BeautifulUrl includes this file.
960
+ # =================================================================== #
961
+ elsif BeautifulUrl.does_include?(this_file) # open linux
962
+ _ = beautiful_url(this_file)
963
+ consider_opening_the_given_input(_) # Then try again.
964
+ # =================================================================== #
965
+ # Ok, the following else-clauses handle the situation
966
+ # that the given input could not be found.
967
+ # =================================================================== #
968
+ elsif this_file.include? 'project_'
969
+ do_open_in_editor(this_file)
970
+ # =================================================================== #
971
+ # At the least one entry has been found.
972
+ # =================================================================== #
973
+ elsif ((_ = possible_matches).size > 0) # If we can find at least one entry.
974
+ consider_opening_the_given_input(_.first) # Recursive call.
975
+ # =================================================================== #
976
+ # Same as above, but both prepend and append a '*' character.
977
+ # =================================================================== #
978
+ elsif ((_ = possible_matches).size > 0) # If we can find at least one entry.
979
+ consider_opening_the_given_input(_.first)
980
+ # =================================================================== #
981
+ # Next, try to pass it through class Roebe::FindExpandedAlias.
982
+ # =================================================================== #
983
+ elsif File.exist?(_ = Roebe.find_expanded_alias(this_file).to_s)
984
+ open_in_editor(_)
985
+ # =================================================================== #
986
+ # Next, try to handle input containing two ':' tokens.
987
+ # =================================================================== #
988
+ elsif this_file.include?('::')
989
+ try_to_find_files_based_on_hyphens_as_part_of_the_input(this_file)
990
+ # =================================================================== #
991
+ # Use RUBY_SRC as shortcut on my home system.
992
+ # =================================================================== #
993
+ elsif is_on_roebe? and
994
+ File.exist?(return_assumed_path_to_ruby_src_lib_of(this_file))
995
+ use_this_file_instead = return_assumed_path_to_ruby_src_lib_of(this_file)
996
+ e rev+'Since we are on roebe, we will use another path, aka'
997
+ e
998
+ e " #{steelblue(use_this_file_instead)}"
999
+ e
1000
+ open_in_editor(use_this_file_instead)
1001
+ # =================================================================== #
1002
+ # === Check for aliases next
1003
+ #
1004
+ # Next, try to find an expanded alias here.
1005
+ # =================================================================== #
1006
+ elsif Roebe.const_defined?(:FindExpandedAlias) and
1007
+ (::Roebe::FindExpandedAlias[this_file] != this_file)
1008
+ do_open_in_editor(this_file)
1009
+ else
1010
+ opnn; e 'No match could be found for `'+sfancy(this_file)+'`.'
1011
+ end
1012
+ end
1013
+ }
1014
+ end
1015
+
1016
+ # ========================================================================= #
1017
+ # === run (run tag)
1018
+ # ========================================================================= #
1019
+ def run
1020
+ check_whether_the_user_has_provided_any_input
1021
+ try_to_require_the_studium_project
1022
+ try_to_require_the_beautiful_url_project
1023
+ menu
1024
+ run_everything
1025
+ end
1026
+
1027
+ # ========================================================================= #
1028
+ # === Open::Open[]
1029
+ # ========================================================================= #
1030
+ def self.[](i = ARGV, &block)
1031
+ new(i, &block) # Always delegate here.
1032
+ end
1033
+
1034
+ end
1035
+
1036
+ # =========================================================================== #
1037
+ # === Open.open
1038
+ # =========================================================================== #
1039
+ def self.open(i = ARGV, &block)
1040
+ ::Open::Open.new(i, &block)
1041
+ end; self.instance_eval { alias [] open } # === Open[]
1042
+
1043
+ # =========================================================================== #
1044
+ # === Open.pdf_viewer?
1045
+ # =========================================================================== #
1046
+ def self.pdf_viewer?
1047
+ unless (Object.const_defined?(:PdfParadise) and PdfParadise.const_defined?(:MainPdf))
1048
+ require 'pdf_paradise/main_pdf/main_pdf.rb'
1049
+ end
1050
+ return ::PdfParadise.use_which_pdf_viewer?
1051
+ end
1052
+
1053
+ end
1054
+
1055
+ if __FILE__ == $PROGRAM_NAME
1056
+ Open::Open.new(ARGV)
1057
+ end # open