open 0.1.22

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