ruby-zoom 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,48 @@
1
+ require "shellwords"
2
+ require "zoom_profile"
3
+
4
+ class AckProfile < ZoomProfile
5
+ def colors
6
+ 'ACK_COLOR_LINENO=white ACK_COLOR_MATCH="black on_white"'
7
+ end
8
+
9
+ def exe(args, pattern)
10
+ if (pattern.nil? || pattern.empty?)
11
+ system(
12
+ "#{self.to_s} --pager \"#{@pager}\" #{args} " \
13
+ "#{self.append}"
14
+ )
15
+ else
16
+ system(
17
+ "#{self.to_s} --pager \"#{@pager}\" #{args} " \
18
+ "#{pattern.shellescape} #{self.append}"
19
+ )
20
+ end
21
+ end
22
+
23
+ def initialize(
24
+ operator = nil,
25
+ flags = "--smart-case",
26
+ envprepend = "",
27
+ append = ""
28
+ )
29
+ # Special case because of debian
30
+ operator = nil
31
+ if (ScoobyDoo.where_are_you("ack"))
32
+ operator = "ack"
33
+ elsif (ScoobyDoo.where_are_you("ack-grep"))
34
+ operator = "ack-grep"
35
+ else
36
+ # Oops
37
+ operator = "echo"
38
+ if (operator == "echo")
39
+ flags = "#"
40
+ envprepend = ""
41
+ append = ""
42
+ end
43
+ end
44
+
45
+ super(operator, flags, envprepend, append)
46
+ @taggable = true
47
+ end
48
+ end
@@ -0,0 +1,41 @@
1
+ require "shellwords"
2
+ require "zoom_profile"
3
+
4
+ class AgProfile < ZoomProfile
5
+ def colors
6
+ '--color-match "47;1;30" --color-line-number "0;37"'
7
+ end
8
+
9
+ def exe(args, pattern)
10
+ if (pattern.nil? || pattern.empty?)
11
+ system(
12
+ "#{self.to_s} --pager \"#{@pager}\" #{args} " \
13
+ "#{self.append}"
14
+ )
15
+ else
16
+ system(
17
+ "#{self.to_s} --pager \"#{@pager}\" #{args} " \
18
+ "#{pattern.shellescape} #{self.append}"
19
+ )
20
+ end
21
+ end
22
+
23
+ def initialize(
24
+ operator = nil,
25
+ flags = "-S",
26
+ envprepend = "",
27
+ append = ""
28
+ )
29
+ super("ag", flags, envprepend, append)
30
+ @taggable = true
31
+ end
32
+
33
+ def to_s
34
+ [
35
+ self["prepend"],
36
+ self["operator"],
37
+ self.colors,
38
+ self["flags"]
39
+ ].join(" ").strip
40
+ end
41
+ end
@@ -0,0 +1,28 @@
1
+ require "shellwords"
2
+ require "zoom_profile"
3
+
4
+ class FindProfile < ZoomProfile
5
+ def exe(args, pattern)
6
+ if (pattern.nil? || pattern.empty?)
7
+ system(
8
+ "#{self.to_s} #{args} \"*\" #{self.append} | " \
9
+ "#{@pager}"
10
+ )
11
+ else
12
+ system(
13
+ "#{self.to_s} #{args} \"#{pattern}\" " \
14
+ "#{self.append} | #{@pager}"
15
+ )
16
+ end
17
+ end
18
+
19
+ def initialize(
20
+ operator = nil,
21
+ flags = ". -name",
22
+ envprepend = "",
23
+ append = ""
24
+ )
25
+ super("find", flags, envprepend, append)
26
+ @taggable = true
27
+ end
28
+ end
@@ -0,0 +1,48 @@
1
+ require "shellwords"
2
+ require "zoom_profile"
3
+
4
+ class GrepProfile < ZoomProfile
5
+ def colors
6
+ [
7
+ 'GREP_COLORS="',
8
+ "fn=1;32:",
9
+ "ln=0;37:",
10
+ "ms=47;1;30:",
11
+ "mc=47;1;30:",
12
+ "sl=:cx=:bn=:se=",
13
+ '"'
14
+ ].join.strip
15
+ end
16
+
17
+ def exe(args, pattern)
18
+ # Emulate ag/ack as much as possible
19
+ if (pattern.nil? || pattern.empty?)
20
+ system(
21
+ "#{self.to_s} #{args} #{self.append} | " \
22
+ "sed \"s|\\[K[:-]|\\[K\\n|\" | #{@pager}"
23
+ )
24
+ else
25
+ system(
26
+ "#{self.to_s} #{args} #{pattern.shellescape} " \
27
+ "#{self.append} | sed \"s|\\[K[:-]|\\[K\\n|\" | " \
28
+ "#{@pager}"
29
+ )
30
+ end
31
+ end
32
+
33
+ def initialize(
34
+ operator = nil,
35
+ flags = [
36
+ "--color=always",
37
+ "-EHIinR",
38
+ "--exclude-dir=.bzr",
39
+ "--exclude-dir=.git",
40
+ "--exclude-dir=.svn"
41
+ ].join(" ").strip,
42
+ envprepend = "",
43
+ append = "."
44
+ )
45
+ super("grep", flags, envprepend, append)
46
+ @taggable = true
47
+ end
48
+ end
@@ -0,0 +1,67 @@
1
+ require "ag_profile"
2
+ require "ack_profile"
3
+ require "grep_profile"
4
+ require "shellwords"
5
+ require "zoom_profile"
6
+
7
+ class PasswordsProfile < ZoomProfile
8
+ def colors
9
+ return @profile.colors
10
+ end
11
+
12
+ def exe(args, pattern)
13
+ @profile.exe(args, pattern)
14
+ end
15
+
16
+ def info
17
+ [
18
+ "Class : #{self.class.to_s}",
19
+ "Prepend : #{@profile.prepend}",
20
+ "Operator: #{@profile.operator}",
21
+ "Flags : #{@profile.flags}",
22
+ "Append : #{@profile.append}"
23
+ ].join("\n").strip
24
+ end
25
+
26
+ def initialize(
27
+ operator = nil,
28
+ flags = "",
29
+ envprepend = "",
30
+ append = ""
31
+ )
32
+ @passwd_regex = "\"pass(word|wd)?[^:=,>]? *[:=,>]\""
33
+
34
+ if (ScoobyDoo.where_are_you("ag"))
35
+ @profile = AgProfile.new(nil, "-uS", "", @passwd_regex)
36
+ elsif (
37
+ ScoobyDoo.where_are_you("ack") ||
38
+ ScoobyDoo.where_are_you("ack-grep")
39
+ )
40
+ @profile = AckProfile.new(
41
+ nil,
42
+ "--smart-case",
43
+ "",
44
+ @passwd_regex
45
+ )
46
+ else
47
+ @profile = GrepProfile.new(
48
+ nil,
49
+ "--color=always -EHinR",
50
+ "",
51
+ @passwd_regex
52
+ )
53
+ end
54
+
55
+ super(
56
+ @profile.operator,
57
+ @profile.flags,
58
+ @profile.prepend,
59
+ @profile.append
60
+ )
61
+ @taggable = true
62
+ end
63
+
64
+ def to_s
65
+ return @porfile.to_s
66
+ end
67
+ end
@@ -0,0 +1,26 @@
1
+ # Redefine String class to allow for colorizing and rsplit
2
+ class String
3
+ def blue
4
+ return colorize(36)
5
+ end
6
+
7
+ def colorize(color)
8
+ return "\e[#{color}m#{self}\e[0m"
9
+ end
10
+
11
+ def green
12
+ return colorize(32)
13
+ end
14
+
15
+ def red
16
+ return colorize(31)
17
+ end
18
+
19
+ def white
20
+ return colorize(37)
21
+ end
22
+
23
+ def word_wrap(width = 70)
24
+ return scan(/\S.{0,#{width}}\S(?=\s|$)|\S+/).join("\n")
25
+ end
26
+ end
@@ -0,0 +1,621 @@
1
+ require "ack_profile"
2
+ require "ag_profile"
3
+ require "find_profile"
4
+ require "grep_profile"
5
+ require "io/wait"
6
+ require "json"
7
+ require "pathname"
8
+ require "passwords_profile"
9
+ require "singleton"
10
+ require "string"
11
+ require "zoom_error"
12
+ require "zoom_profile"
13
+
14
+ class Zoom
15
+ include Singleton
16
+ include ZoomError
17
+
18
+ def add_profile(
19
+ name,
20
+ clas,
21
+ operator = nil,
22
+ flags = nil,
23
+ envprepend = nil,
24
+ append = nil
25
+ )
26
+ if (@profiles.has_key?(name))
27
+ raise ZoomError::ProfileAlreadyExistsError.new(name)
28
+ end
29
+
30
+ default_class = nil
31
+ begin
32
+ default_class = Object::const_get(clas).new
33
+ rescue NameError => e
34
+ raise ZoomError::ProfileClassUnknownError.new(clas)
35
+ end
36
+
37
+ edit_profile(
38
+ name,
39
+ default_class,
40
+ operator,
41
+ flags,
42
+ envprepend,
43
+ append
44
+ )
45
+ end
46
+
47
+ def clear_cache
48
+ @cache_file.delete if (@cache_file.exist?)
49
+ end
50
+
51
+ def configure_editor(editor)
52
+ e = ScoobyDoo.where_are_you(editor)
53
+ if (e.nil?)
54
+ raise ZoomError::ExecutableNotFoundError.new(editor)
55
+ end
56
+
57
+ @rc["editor"] = e
58
+ write_zoomrc
59
+ end
60
+
61
+ def default
62
+ default_zoominfo
63
+ default_zoomrc
64
+ end
65
+
66
+ def default_zoominfo
67
+ @info = Hash.new
68
+ @info["profile"] = "default"
69
+
70
+ # Reset last command to be empty
71
+ @info["last_command"] = Hash.new
72
+
73
+ write_zoominfo
74
+ end
75
+ private :default_zoominfo
76
+
77
+ def default_zoomrc
78
+ @rc = Hash.new
79
+ @profiles = Hash.new
80
+
81
+ all = nil
82
+
83
+ # Default ag profiles
84
+ if (ScoobyDoo.where_are_you("ag"))
85
+ ag = AgProfile.new
86
+ all = AgProfile.new(nil, "-uS")
87
+ else
88
+ ag = nil
89
+ end
90
+
91
+ # Default ack profile
92
+ if (
93
+ ScoobyDoo.where_are_you("ack") ||
94
+ ScoobyDoo.where_are_you("ack-grep")
95
+ )
96
+ ack = AckProfile.new
97
+ else
98
+ ack = nil
99
+ end
100
+
101
+ # Default grep profile (emulate ag/ack as much as possible)
102
+ grep = GrepProfile.new
103
+ if (all.nil?)
104
+ all = GrepProfile.new
105
+ all.flags("--color=always -EHinR")
106
+ end
107
+
108
+ # Create default profile
109
+ if (ag)
110
+ default = ag
111
+ elsif (ack)
112
+ default = ack
113
+ else
114
+ default = grep
115
+ end
116
+
117
+ # Create find profile
118
+ find = FindProfile.new
119
+
120
+ # Put profiles into rc
121
+ @profiles["ack"] = ack if (ack)
122
+ @profiles["ag"] = ag if (ag)
123
+ @profiles["all"] = all if (all)
124
+ @profiles["default"] = default
125
+ @profiles["grep"] = grep
126
+ @profiles["passwords"] = PasswordsProfile.new
127
+ @profiles["zoom_find"] = find
128
+
129
+ # Default editor (use $EDITOR)
130
+ @rc["editor"] = ""
131
+
132
+ write_zoomrc
133
+ end
134
+ private :default_zoomrc
135
+
136
+ def delete_profile(name)
137
+ if (name == "default")
138
+ raise ZoomError::ProfileCanNotBeModifiedError.new(name)
139
+ end
140
+
141
+ if (name == "zoom_find")
142
+ raise ZoomError::ProfileCanNotBeModifiedError.new(name)
143
+ end
144
+
145
+ if (!@profiles.has_key?(name))
146
+ raise ZoomError::ProfileDoesNotExistError.new(name)
147
+ end
148
+
149
+ @profiles.delete(name)
150
+ write_zoomrc
151
+
152
+ if (name == @info["profile"])
153
+ @info["profile"] = "default"
154
+ write_zoominfo
155
+ end
156
+ end
157
+
158
+ def edit_profile(
159
+ name,
160
+ profile = nil,
161
+ operator = nil,
162
+ flags = nil,
163
+ envprepend = nil,
164
+ append = nil
165
+ )
166
+ if (name == "zoom_find")
167
+ raise ZoomError::ProfileCanNotBeModified.new(name)
168
+ end
169
+
170
+ profile = @profiles[name] if (profile.nil?)
171
+
172
+ if (profile.nil?)
173
+ raise ZoomError::ProfileDoesNotExists.new(name)
174
+ end
175
+
176
+ profile.operator(operator) if (operator)
177
+ profile.flags(flags) if (flags)
178
+ profile.prepend(envprepend) if (envprepend)
179
+ profile.append(append) if (append)
180
+
181
+ @profiles[name] = profile
182
+ write_zoomrc
183
+ end
184
+
185
+ def exec_profile(name, args, pattern)
186
+ name = @info["profile"] if (name.nil?)
187
+
188
+ if (!@profiles.has_key?(name))
189
+ raise ZoomError::ProfileDoesNotExistError.new(name)
190
+ end
191
+
192
+ @info["last_command"] = {
193
+ "profile" => name,
194
+ "subargs" => args.nil? ? "": args,
195
+ "pattern" => pattern.nil? ? "" : pattern
196
+ }
197
+ write_zoominfo
198
+
199
+ profile = @profiles[name]
200
+ begin
201
+ clear_cache if (profile.taggable)
202
+ profile.exe(args, pattern)
203
+ shortcut_cache(profile) if (profile.taggable)
204
+ rescue Interrupt
205
+ # ^C
206
+ end
207
+ end
208
+
209
+ def get_location_of_result(result)
210
+ count = 0
211
+ File.open(@shortcut_file) do |file|
212
+ file.each do |line|
213
+ count += 1
214
+ if (count == result)
215
+ return line
216
+ end
217
+ end
218
+ end
219
+ return nil
220
+ end
221
+ private :get_location_of_result
222
+
223
+ def get_new_value(val, default)
224
+ return default if (val.nil? || val.empty?)
225
+ return "" if (val.downcase == "empty")
226
+ return "" if (val.downcase == "\"empty\"")
227
+ return val
228
+ end
229
+ private :get_new_value
230
+
231
+ def initialize
232
+ # Load custom profiles
233
+ custom_profs = Pathname.new("~/.zoom_profiles.rb").expand_path
234
+ require_relative custom_profs if (custom_profs.exist?)
235
+
236
+ @cache_file = Pathname.new("~/.zoom_cache").expand_path
237
+ @info_file = Pathname.new("~/.zoominfo").expand_path
238
+ @rc_file = Pathname.new("~/.zoomrc").expand_path
239
+ @shortcut_file = Pathname.new("~/.zoom_shortcuts").expand_path
240
+
241
+ read_zoomrc
242
+ read_zoominfo
243
+
244
+ # Setup editor
245
+ @editor = @rc["editor"]
246
+ @editor = ENV["EDITOR"] if (@editor.nil? || @editor.empty?)
247
+ @editor = "vim" if (@editor.nil? || @editor.empty?)
248
+ @editor = ScoobyDoo.where_are_you(@editor)
249
+ @editor = ScoobyDoo.where_are_you("vi") if (@editor.nil?)
250
+ end
251
+
252
+ def interactive_add_profile(name)
253
+ if (@profiles.has_key?(name))
254
+ raise ZoomError::ProfileAlreadyExistsError.new(name)
255
+ end
256
+
257
+ default_op = "grep"
258
+ if (ScoobyDoo.where_are_you("ag"))
259
+ default_op = "ag"
260
+ elsif (ScoobyDoo.where_are_you("ack"))
261
+ default_op = "ack"
262
+ elsif (ScoobyDoo.where_are_you("ack-grep"))
263
+ default_op = "ack-grep"
264
+ end
265
+
266
+ case default_op
267
+ when "ack", "ack-grep"
268
+ puts "Enter class (default AckProfile):"
269
+ when "ag"
270
+ puts "Enter class (default AgProfile):"
271
+ when "grep"
272
+ puts "Enter class (default GrepProfile):"
273
+ end
274
+
275
+ clas = gets.chomp
276
+ puts if (clas && !clas.empty?)
277
+
278
+ case default_op
279
+ when "ack", "ack-grep"
280
+ clas = "AckProfile" if (clas.nil? || clas.empty?)
281
+ when "ag"
282
+ clas = "AgProfile" if (clas.nil? || clas.empty?)
283
+ when "grep"
284
+ clas = "GrepProfile" if (clas.nil? || clas.empty?)
285
+ end
286
+
287
+ add_profile(name, clas)
288
+ interactive_edit_profile(name)
289
+ end
290
+
291
+ def interactive_edit_profile(name, profile = nil)
292
+ if (name == "zoom_find")
293
+ raise ZoomError::ProfileCanNotBeModifiedError.new(name)
294
+ end
295
+
296
+ profile = @profiles[name] if (profile.nil?)
297
+
298
+ if (profile.nil?)
299
+ raise ZoomError::ProfileDoesNotExistError.new(name)
300
+ end
301
+
302
+ # Get new operator
303
+ puts "Enter operator (default #{profile.operator}):"
304
+
305
+ op = ScoobyDoo.where_are_you(gets.chomp)
306
+ puts if (op && !op.empty?)
307
+ op = profile.operator if (op.nil? || op.empty?)
308
+
309
+ # Get new flags
310
+ puts "For empty string put \"empty\""
311
+ puts "Enter flags (default \"#{profile.flags}\"):"
312
+
313
+ flags = gets.chomp
314
+ puts if (flags && !flags.empty?)
315
+ flags = get_new_value(flags, profile.flags)
316
+
317
+ # Get new prepend
318
+ puts "For empty string put \"empty\""
319
+ puts "Enter prepend (default \"#{profile.prepend}\"):"
320
+
321
+ envprepend = gets.chomp
322
+ puts if (envprepend && !envprepend.empty?)
323
+ envprepend = get_new_value(envprepend, profile.prepend)
324
+
325
+ # Get new append
326
+ puts "For empty string put \"empty\""
327
+ puts "Enter append (default \"#{profile.append}\"):"
328
+
329
+ append = gets.chomp
330
+ puts if (append && !append.empty?)
331
+ append = get_new_value(append, profile.append)
332
+
333
+ edit_profile(name, profile, op, flags, envprepend, append)
334
+ end
335
+
336
+ def list_profile_names
337
+ @profiles.keys.sort.each do |name|
338
+ puts name
339
+ end
340
+ end
341
+
342
+ def list_profiles
343
+ @profiles.keys.sort.each do |name|
344
+ if (name == @info["profile"])
345
+ puts "### #{name} ###".green
346
+ else
347
+ puts "### #{name} ###"
348
+ end
349
+ puts @profiles[name].info
350
+ puts
351
+ end
352
+ end
353
+
354
+ def list_tags
355
+ return if (!@cache_file.exist?)
356
+
357
+ # Open shortcut file for writing
358
+ shct = File.open(@shortcut_file, "r")
359
+
360
+ # Read in cache
361
+ File.open(@cache_file) do |cache|
362
+ count = 1
363
+
364
+ cache.each do |line|
365
+ line.chomp!
366
+ plain = remove_colors(line)
367
+ if (line.start_with?("ZOOM_EXE_DIR="))
368
+ # Ignore this line
369
+ elsif ((line == "-") || (line == "--") || line.empty?)
370
+ # Ignore dividers when searching with context and
371
+ # empty lines
372
+ elsif (plain.scan(/^[0-9]+[:-]/).empty?)
373
+ if (!plain.scan(/^\.\//).empty?)
374
+ # Operator was probably find
375
+ puts count
376
+ count += 1
377
+ end
378
+ else
379
+ puts count
380
+ count += 1
381
+ end
382
+ end
383
+ end
384
+ end
385
+
386
+ def loop_through_results(results)
387
+ tags = parse_tags(results)
388
+ return if (tags.empty?)
389
+
390
+ tag = tags.delete_at(0)
391
+ open_editor_to_result(tag)
392
+
393
+ tags.each do |tag|
394
+ print "Do you want to open result #{tag} [y]/n/q/l?: "
395
+
396
+ answer = nil
397
+ while (answer.nil?)
398
+ begin
399
+ system("stty raw -echo")
400
+ if ($stdin.ready?)
401
+ answer = $stdin.getc
402
+ else
403
+ sleep 0.1
404
+ end
405
+ ensure
406
+ system("stty -raw echo")
407
+ end
408
+ end
409
+ puts
410
+
411
+ case answer
412
+ when "n", "N"
413
+ # Do nothing
414
+ when "l", "L"
415
+ # Open this result then exit
416
+ open_editor_to_result(tag)
417
+ return
418
+ when "q", "Q", "\x03"
419
+ # Quit or ^C
420
+ return
421
+ else
422
+ open_editor_to_result(tag)
423
+ end
424
+ end
425
+ end
426
+
427
+ def open_editor_to_result(result)
428
+ loc = get_location_of_result(result.to_i)
429
+ if (loc)
430
+ system("#{@editor} #{loc}")
431
+ else
432
+ puts "Invalid tag \"#{result}\"!"
433
+ end
434
+ end
435
+ private :open_editor_to_result
436
+
437
+ def pager
438
+ File.open(@cache_file, "w") do |f|
439
+ f.write("ZOOM_EXE_DIR=#{Dir.pwd}\n")
440
+ begin
441
+ $stdin.each_line do |line|
442
+ f.write(line)
443
+ end
444
+ rescue Interrupt
445
+ # ^C
446
+ end
447
+ end
448
+ end
449
+
450
+ def parse_tags(results)
451
+ tags = Array.new
452
+ results.split(",").each do |num|
453
+ if (!num.scan(/^[0-9]+$/).empty?)
454
+ tags.push(num.to_i)
455
+ elsif (!num.scan(/^[0-9]+-[0-9]+$/).empty?)
456
+ range = num.split("-")
457
+ (range[0].to_i..range[1].to_i).each do |i|
458
+ tags.push(i)
459
+ end
460
+ else
461
+ puts "Tag #{num} not formatted properly. Ignoring."
462
+ end
463
+ end
464
+ return tags
465
+ end
466
+ private :parse_tags
467
+
468
+ def read_zoominfo
469
+ if (!@info_file.exist? && !@info_file.symlink?)
470
+ default_zoominfo
471
+ end
472
+
473
+ @info = JSON.parse(File.read(@info_file))
474
+ end
475
+ private :read_zoominfo
476
+
477
+ def read_zoomrc
478
+ default_zoomrc if (!@rc_file.exist? && !@rc_file.symlink?)
479
+
480
+ @rc = JSON.parse(File.read(@rc_file))
481
+ @profiles = Hash.new
482
+ @rc["profiles"].each do |name, prof|
483
+ @profiles[name] = ZoomProfile.from_json(prof)
484
+ end
485
+ @rc["profiles"] = @profiles
486
+ end
487
+ private :read_zoomrc
488
+
489
+ def rename_profile(rename, name = nil)
490
+ name = @info["profile"] if (name.nil?)
491
+
492
+ if ((name == "default") || (name == "zoom_find"))
493
+ raise ZoomError::ProfileCanNotBeModifiedError.new(name)
494
+ end
495
+
496
+ if (!@profiles.has_key?(name))
497
+ raise ZoomError::ProfileDoesNotExistError.new(name)
498
+ end
499
+
500
+ if (@profiles.has_key?(rename))
501
+ raise ZoomError::ProfileAlreadyExistsError.new(rename)
502
+ end
503
+
504
+ @profiles[rename] = @profiles[name]
505
+ @profiles.delete(name)
506
+ write_zoomrc
507
+
508
+ if (name == @info["profile"])
509
+ @info["profile"] = rename
510
+ write_zoominfo
511
+ end
512
+ end
513
+
514
+ def repeat
515
+ return if (@info["last_command"].empty?)
516
+
517
+ exe_command(
518
+ @info["last_command"]["profile"],
519
+ @info["last_command"]["subargs"],
520
+ @info["last_command"]["pattern"]
521
+ )
522
+ end
523
+
524
+ def remove_colors(str)
525
+ str.unpack("C*").pack("U*").gsub(/\e\[([0-9;]*m|K)/, "")
526
+ end
527
+ private :remove_colors
528
+
529
+ def shortcut_cache(profile = nil)
530
+ return if (!@cache_file.exist?)
531
+ return if (@info["last_command"].empty?)
532
+
533
+ if (profile.nil?)
534
+ profile = @profiles[@info["last_command"]["profile"]]
535
+ end
536
+
537
+ # Open shortcut file for writing
538
+ shct = File.open(@shortcut_file, "w")
539
+
540
+ # Read in cache
541
+ File.open(@cache_file) do |cache|
542
+ start_dir = ""
543
+ file = nil
544
+ filename = ""
545
+ first_time = true
546
+ count = 1
547
+
548
+ cache.each do |line|
549
+ line.chomp!
550
+ plain = remove_colors(line)
551
+ if (line.start_with?("ZOOM_EXE_DIR="))
552
+ # Get directory where search was ran
553
+ start_dir = line.gsub("ZOOM_EXE_DIR=", "")
554
+ elsif ((line == "-") || (line == "--") || line.empty?)
555
+ # Ignore dividers when searching with context and
556
+ # empty lines
557
+ elsif (plain.scan(/^[0-9]+[:-]/).empty?)
558
+ operator = profile.operator.split("/").last
559
+ if (operator != "find")
560
+ if (file != line)
561
+ # Filename
562
+ file = line
563
+ filename = remove_colors(file)
564
+
565
+ puts if (!first_time)
566
+ first_time = false
567
+
568
+ puts "\e[0m#{file}"
569
+ end
570
+ else
571
+ # Operator was find
572
+ puts "\e[1;31m[#{count}]\e[0m #{line}"
573
+ shct.write("'#{start_dir}/#{line}'\n")
574
+ count += 1
575
+ end
576
+ elsif (file)
577
+ # Match
578
+ sanitized = line.unpack("C*").pack("U*")
579
+ .gsub(/[\u0080-\u00ff]+/, "\1".dump[1..-2])
580
+ puts "\e[1;31m[#{count}]\e[0m #{sanitized}"
581
+
582
+ lineno = remove_colors(line).split(/[:-]/)[0]
583
+ shct.write(
584
+ "+#{lineno} '#{start_dir}/#{filename}'\n"
585
+ )
586
+
587
+ count += 1
588
+ end
589
+ end
590
+ end
591
+ end
592
+
593
+ def show_current
594
+ puts "### #{@info["profile"]} ###".green
595
+ puts @profiles[@info["profile"]].info
596
+ end
597
+
598
+ def switch_profile(name)
599
+ if (!@profiles.has_key?(name))
600
+ raise ZoomError::ProfileDoesNotExistError.new(name)
601
+ end
602
+
603
+ @info["profile"] = name
604
+ write_zoominfo
605
+ end
606
+
607
+ def write_zoominfo
608
+ File.open(@info_file, "w") do |file|
609
+ file.write(JSON.pretty_generate(@info))
610
+ end
611
+ end
612
+ private :write_zoominfo
613
+
614
+ def write_zoomrc
615
+ @rc["profiles"] = @profiles
616
+ File.open(@rc_file, "w") do |file|
617
+ file.write(JSON.pretty_generate(@rc))
618
+ end
619
+ end
620
+ private :write_zoomrc
621
+ end