ruby-zoom 4.7.5 → 5.0.0

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/zoom.rb CHANGED
@@ -5,6 +5,77 @@ class Zoom
5
5
  attr_reader :cache
6
6
  attr_reader :config
7
7
 
8
+ def ensure_valid_header(header)
9
+ # Ensure header has no nil
10
+ header["args"] ||= ""
11
+ header["debug"] ||= false
12
+ header["paths"] ||= "."
13
+ header["paths"] = "." if (header["paths"].empty?)
14
+ header["profile_name"] ||= ""
15
+ header["pwd"] = Dir.pwd
16
+ header["regex"] ||= ""
17
+ header["translate"] ||= Hash.new
18
+
19
+ # If no profile name, use the current profile
20
+ profile_name = header["profile_name"]
21
+ if (profile_name.empty?)
22
+ profile_name = @config.current_profile_name
23
+ header["profile_name"] = profile_name
24
+ end
25
+
26
+ if (!@config.has_profile?(profile_name))
27
+ raise Zoom::Error::ProfileDoesNotExist.new(profile_name)
28
+ end
29
+
30
+ profile = @config.get_profile(profile_name)
31
+
32
+ # Use hard-coded regex if defined
33
+ if (
34
+ profile.regex &&
35
+ !profile.regex.empty? &&
36
+ (header["regex"] != profile.regex)
37
+ )
38
+ # If there was a regex then it may be an arg or a path
39
+ if (!header["regex"].empty?)
40
+ if (Pathname.new(header["regex"]).exist?)
41
+ header["paths"] = "" if (header["paths"] == ".")
42
+ paths = header["paths"].split(" ")
43
+ paths.insert(0, header["regex"])
44
+ header["paths"] = paths.join(" ")
45
+ else
46
+ header["args"] += " #{header["regex"]}"
47
+ end
48
+ end
49
+
50
+ header["regex"] = profile.regex
51
+ end
52
+
53
+ # If using a search tool
54
+ if (!profile.format_flags.empty?)
55
+ if (header["regex"].empty? && header["paths"] == ".")
56
+ # Throw exception because no regex was provided or
57
+ # hard-coded
58
+ raise Zoom::Error::RegexNotProvided.new
59
+ end
60
+
61
+ # This isn't done here anymore as it breaks stuff
62
+ # header["regex"] = header["regex"].shellescape
63
+ end
64
+
65
+ # Strip values
66
+ header.keys.each do |key|
67
+ next if (key == "regex")
68
+ begin
69
+ header[key].strip!
70
+ rescue
71
+ # Wasn't a String
72
+ end
73
+ end
74
+
75
+ return header
76
+ end
77
+ private :ensure_valid_header
78
+
8
79
  def self.hilight(hilight = true)
9
80
  @@hilight = hilight
10
81
  end
@@ -22,10 +93,7 @@ class Zoom
22
93
 
23
94
  def open(results)
24
95
  return if (results.nil? || results.empty?)
25
-
26
- # All results should be from the same profile
27
- profile = @config.get_profile(results[0].profile_name)
28
- profile.go(@config.editor, results)
96
+ Zoom::Editor.new(@config.editor).open(results)
29
97
  end
30
98
 
31
99
  def repeat(shortcut = true)
@@ -33,39 +101,34 @@ class Zoom
33
101
  run(@cache.header, shortcut, true)
34
102
  end
35
103
 
36
- def run(header, shortcut = true, repeat = false)
37
- # Ensure header has no nil
38
- ["args", "pattern", "profile_name"].each do |key|
39
- header[key] ||= ""
40
- end
41
- header["paths"] ||= "."
42
- header["pwd"] = Dir.pwd
43
- header["translate"] ||= Array.new
44
-
45
- profile_name = header["profile_name"]
46
- if (profile_name.empty?)
47
- profile_name = @config.current_profile_name
48
- header["profile_name"] = profile_name
49
- end
104
+ def run(h, shortcut = true, repeat = false)
105
+ # Don't change the header passed in
106
+ header = h.clone
50
107
 
51
- if (!@config.has_profile?(profile_name))
52
- raise Zoom::Error::ProfileDoesNotExist.new(profile_name)
53
- end
108
+ # Ensure header is formatted properly and valid
109
+ header = ensure_valid_header(header) if (!repeat)
54
110
 
111
+ profile_name = header["profile_name"]
55
112
  profile = @config.get_profile(profile_name)
56
- begin
57
- # This will translate and/or append args such that the
58
- # output will be something Zoom can process
59
- header = profile.preprocess(header) if (!repeat)
60
113
 
114
+ begin
61
115
  # Clear cache
62
116
  @cache.clear
63
117
 
64
118
  # Store needed details
65
119
  @cache.header(header)
66
120
 
121
+ # Translate any needed flags
122
+ header["translated"] = profile.translate(
123
+ header["translate"]
124
+ ).strip
125
+
126
+ # This may append args such that the output will be
127
+ # something Zoom can process
128
+ header = profile.preprocess(header)
129
+
67
130
  # Execute profile
68
- @cache.write(profile.exe(header), header["pattern"])
131
+ @cache.write(profile.exe(header), header["regex"])
69
132
 
70
133
  # Display results from cache
71
134
  @cache.shortcut(@config) if (shortcut)
data/lib/zoom/cache.rb CHANGED
@@ -111,11 +111,6 @@ class Zoom::Cache
111
111
  return @header["paths"]
112
112
  end
113
113
 
114
- def pattern
115
- return nil if (@header.nil?)
116
- return @header["pattern"]
117
- end
118
-
119
114
  def profile_name
120
115
  return nil if (@header.nil?)
121
116
  return @header["profile_name"]
@@ -155,6 +150,11 @@ class Zoom::Cache
155
150
  end
156
151
  end
157
152
 
153
+ def regex
154
+ return nil if (@header.nil?)
155
+ return @header["regex"]
156
+ end
157
+
158
158
  def shortcut(config)
159
159
  return if (empty?)
160
160
 
@@ -184,7 +184,7 @@ class Zoom::Cache
184
184
  config.hilight_tag("[#{result.tag}]"),
185
185
  "#{config.hilight_lineno(result.lineno)}:",
186
186
  result.match.gsub(
187
- /(#{pattern})/i,
187
+ /(#{regex})/i,
188
188
  config.hilight_match("\\1")
189
189
  )
190
190
  ].join(" ")
@@ -204,7 +204,7 @@ class Zoom::Cache
204
204
  end
205
205
  end
206
206
 
207
- def write(str, pattern = nil)
207
+ def write(str, r = nil)
208
208
  return if (str.nil?)
209
209
 
210
210
  if (!str.valid_encoding?)
@@ -217,15 +217,16 @@ class Zoom::Cache
217
217
 
218
218
  File.open(@cache_file, "a") do |f|
219
219
  str.gsub(/\r/, "^M").split("\n").each do |line|
220
- if (pattern && line.match(/^[^:]+:[0-9]+:.+$/))
220
+ if (r && line.match(/^[^:]+:[0-9]+:.+$/))
221
221
  line.match(/^([^:]+:[0-9]+:)(.+)$/) do |m|
222
222
  m[2].scan(
223
- /(.{0,128}#{pattern}.{0,128})/i
223
+ /(.{0,128}#{r}.{0,128})/i
224
224
  ) do |n|
225
225
  f.write("#{m[1]}#{n[0]}\n")
226
226
  end
227
227
  end
228
228
  else
229
+ line.gsub!(/^(.{128}).*(.{128})$/, "\\1...\\2")
229
230
  f.write("#{line}\n")
230
231
  end
231
232
  end
@@ -28,12 +28,12 @@ class Zoom::Cache::Result
28
28
  @filename = "Binary file"
29
29
  @contents = m[1]
30
30
  end
31
- when /^([^:]+):(\d+)[:-](.*)$/
32
- @contents.match(/^([^:]+):(\d+)[:-](.*)$/) do |m|
31
+ when /^([^:]+)[:-](\d+)[:-](.*)$/
32
+ @contents.match(/^([^:]+)[:-](\d+)[:-](.*)$/) do |m|
33
33
  next if (m.nil?)
34
34
 
35
35
  @grep_like = true
36
- @filename = m[1]
36
+ @filename = m[1].gsub(/^\.\//, "")
37
37
  @lineno = m[2]
38
38
  @match = m[3]
39
39
  end
data/lib/zoom/config.rb CHANGED
@@ -49,7 +49,7 @@ class Zoom::Config < JSONConfig
49
49
  end
50
50
 
51
51
  def default_config
52
- default = Zoom::ProfileManager.default_profile
52
+ default = Zoom::ProfileManager.default_tool
53
53
  profiles = Zoom::ProfileManager.default_profiles
54
54
 
55
55
  clear
@@ -64,20 +64,29 @@ class Zoom::Config < JSONConfig
64
64
  end
65
65
 
66
66
  def editor(ed = nil)
67
- if (ed)
68
- e = ScoobyDoo.where_are_you(ed)
69
- raise Zoom::Error::ExecutableNotFound.new(ed) if (e.nil?)
67
+ if (ed && !ed.empty?)
68
+ e = ed.split(" ")[0]
69
+ if (ScoobyDoo.where_are_you(e).nil?)
70
+ raise Zoom::Error::ExecutableNotFound.new(e)
71
+ end
70
72
  set("editor", ed)
71
73
  end
72
74
 
73
75
  e = get("editor")
74
76
  e = ENV["EDITOR"] if (e.nil? || e.empty?)
75
77
  e = "vim" if (e.nil? || e.empty?)
78
+
79
+ e, _, f = e.partition(" ")
76
80
  e = ScoobyDoo.where_are_you(e)
77
- e = ScoobyDoo.where_are_you("vi") if (e.nil?)
81
+
82
+ if (e.nil?)
83
+ e = ScoobyDoo.where_are_you("vi")
84
+ f = ""
85
+ end
86
+
78
87
  raise Zoom::Error::ExecutableNotFound.new("vi") if (e.nil?)
79
88
 
80
- return e
89
+ return "#{e} #{f}".strip
81
90
  end
82
91
 
83
92
  def has_profile?(name)
data/lib/zoom/editor.rb CHANGED
@@ -42,7 +42,7 @@ class Zoom::Editor
42
42
  private :default
43
43
 
44
44
  def initialize(editor)
45
- @editor = editor
45
+ @editor, _, @flags = editor.partition(" ")
46
46
  end
47
47
 
48
48
  def open(results)
@@ -61,11 +61,13 @@ class Zoom::Editor
61
61
  filename = result.filename
62
62
  lineno = result.lineno
63
63
  pwd = result.pwd
64
- system("#{@editor} +#{lineno} '#{pwd}/#{filename}'")
64
+ system(
65
+ "#{@editor} #{@flags} +#{lineno} '#{pwd}/#{filename}'"
66
+ )
65
67
  else
66
68
  filename = result.contents
67
69
  pwd = result.pwd
68
- system("#{@editor} '#{pwd}/#{filename}'")
70
+ system("#{@editor} #{@flags} '#{pwd}/#{filename}'")
69
71
  end
70
72
  end
71
73
  private :open_result
@@ -113,7 +115,9 @@ class Zoom::Editor
113
115
  zq.close
114
116
  zs.close
115
117
 
116
- system("#{@editor} -S #{source} '#{files.join("' '")}'")
118
+ system(
119
+ "#{@editor} #{@flags} -S #{source} '#{files.join("' '")}'"
120
+ )
117
121
 
118
122
  FileUtils.rm_f(quickfix)
119
123
  FileUtils.rm_f(source)
data/lib/zoom/error.rb CHANGED
@@ -7,3 +7,4 @@ require "zoom/error/invalid_tag"
7
7
  require "zoom/error/profile_class_unknown"
8
8
  require "zoom/error/profile_does_not_exist"
9
9
  require "zoom/error/profile_not_named"
10
+ require "zoom/error/regex_not_provided"
@@ -0,0 +1,5 @@
1
+ class Zoom::Error::RegexNotProvided < Zoom::Error
2
+ def initialize
3
+ super("A regex was not provided or hard-coded")
4
+ end
5
+ end
data/lib/zoom/profile.rb CHANGED
@@ -3,9 +3,11 @@ require "scoobydoo"
3
3
  require "shellwords"
4
4
 
5
5
  class Zoom::Profile < Hash
6
- attr_reader :format_flags
7
- attr_reader :pattern
8
- attr_reader :taggable
6
+ attr_accessor :exts
7
+ attr_accessor :files
8
+ attr_accessor :format_flags
9
+ attr_accessor :regex
10
+ attr_accessor :taggable
9
11
 
10
12
  def after(a = nil)
11
13
  self["after"] = a.strip if (a)
@@ -35,30 +37,26 @@ class Zoom::Profile < Hash
35
37
 
36
38
  def exe(header)
37
39
  # Emulate grep
38
- case operator.split("/")[-1]
39
- when "find"
40
- cmd = [
41
- before,
42
- operator,
43
- header["paths"],
44
- flags,
45
- header["args"],
46
- header["pattern"],
47
- after
48
- ].join(" ").strip
40
+ cmd = [
41
+ before,
42
+ tool,
43
+ @format_flags,
44
+ flags,
45
+ only_exts_and_files,
46
+ header["translated"],
47
+ header["args"],
48
+ "--",
49
+ header["regex"].shellescape,
50
+ header["paths"],
51
+ after
52
+ ].join(" ").strip
53
+
54
+ if (header.has_key?("debug") && header["debug"])
55
+ puts cmd
56
+ return ""
49
57
  else
50
- cmd = [
51
- before,
52
- operator,
53
- @format_flags,
54
- flags,
55
- header["args"],
56
- header["pattern"].shellescape,
57
- header["paths"],
58
- after
59
- ].join(" ").strip
58
+ return %x(#{cmd})
60
59
  end
61
- return %x(#{cmd})
62
60
  end
63
61
 
64
62
  def flags(f = nil)
@@ -71,7 +69,7 @@ class Zoom::Profile < Hash
71
69
  begin
72
70
  return profile_by_name(json["class"]).new(
73
71
  json["name"],
74
- json["operator"].nil? ? "" : json["operator"],
72
+ json["tool"].nil? ? "" : json["tool"],
75
73
  json["flags"].nil? ? "" : json["flags"],
76
74
  json["before"].nil? ? "" : json["before"],
77
75
  json["after"].nil? ? "" : json["after"]
@@ -83,8 +81,9 @@ class Zoom::Profile < Hash
83
81
  end
84
82
  end
85
83
 
86
- def go(editor, results)
87
- Zoom::Editor.new(editor).open(results)
84
+ def grep_like_format_flags(all = false)
85
+ @format_flags = "" # Set this to mirror basic grep
86
+ @taggable = false # Should results be tagged like grep
88
87
  end
89
88
 
90
89
  def hilight_after(str)
@@ -117,34 +116,41 @@ class Zoom::Profile < Hash
117
116
  end
118
117
  private :hilight_name
119
118
 
120
- def hilight_operator(str)
119
+ def hilight_regex(str)
121
120
  return str if (!Zoom.hilight?)
122
- return str.green
121
+ return str
123
122
  end
124
- private :hilight_operator
123
+ private :hilight_regex
125
124
 
126
- def hilight_pattern(str)
125
+ def hilight_tool(str)
127
126
  return str if (!Zoom.hilight?)
128
- return str
127
+ return str.green
129
128
  end
130
- private :hilight_pattern
129
+ private :hilight_tool
131
130
 
132
- def initialize(n = nil, o = nil, f = nil, b = nil, a = nil)
131
+ def initialize(n = nil, t = nil, f = nil, b = nil, a = nil)
133
132
  a ||= ""
134
133
  b ||= ""
135
134
  f ||= ""
136
135
  n ||= camel_case_to_underscore(self.class.to_s)
137
- o ||= "echo"
136
+ t ||= "echo"
138
137
 
139
138
  self["class"] = self.class.to_s
140
139
  after(a)
141
140
  before(b)
142
141
  flags(f)
143
142
  name(n)
144
- operator(o)
143
+ tool(t)
144
+
145
+ @exts = Array.new # Set this to only search specified exts
146
+ @files = Array.new # Set this to noly search specified files
147
+ @regex = "" # Setting this will override user input
145
148
 
146
- @pattern = "" # Setting this will override user input
149
+ # In case someone overrides grep_like_format_flags
150
+ @format_flags = ""
147
151
  @taggable = false
152
+
153
+ grep_like_format_flags
148
154
  end
149
155
 
150
156
  def name(n = nil)
@@ -153,56 +159,12 @@ class Zoom::Profile < Hash
153
159
  return self["name"]
154
160
  end
155
161
 
156
- def operator(o = nil)
157
- if (o)
158
- o.strip!
159
- op = ScoobyDoo.where_are_you(o)
160
- raise Zoom::Error::ExecutableNotFound.new(o) if (op.nil?)
161
- self["operator"] = o
162
- end
163
- return self["operator"]
162
+ def only_exts_and_files
163
+ # Do nothing
164
+ return ""
164
165
  end
165
166
 
166
167
  def preprocess(header)
167
- # Use hard-coded pattern if defined
168
- if (
169
- @pattern &&
170
- !@pattern.empty? &&
171
- (header["pattern"] != @pattern)
172
- )
173
- header["args"] += " #{header["pattern"]}"
174
- header["pattern"] = @pattern
175
- end
176
-
177
- case operator.split("/")[-1]
178
- when /^ack(-grep)?$/, "ag", "grep", "pt"
179
- paths = header["paths"].split(" ")
180
- if (header["pattern"].empty? && !paths.empty?)
181
- header["pattern"] = paths.delete_at(0)
182
- header["paths"] = paths.join(" ").strip
183
- header["paths"] = "." if (header["paths"].empty?)
184
- end
185
-
186
- # This isn't done here anymore as it'll break hilighting
187
- # header["pattern"] = header["pattern"].shellescape
188
- when "find"
189
- # If additional args are passed, then assume pattern is
190
- # actually an arg
191
- if (header["args"] && !header["args"].empty?)
192
- header["args"] += " #{header["pattern"]}"
193
- header["pattern"] = ""
194
- end
195
-
196
- # If pattern was provided then assume it's an iname search
197
- if (header["pattern"] && !header["pattern"].empty?)
198
- header["pattern"] = "-iname \"#{header["pattern"]}\""
199
- end
200
- end
201
-
202
- # Translate any needed flags
203
- header["args"] += " #{translate(header["translate"])}"
204
- header["args"].strip!
205
-
206
168
  return header
207
169
  end
208
170
 
@@ -216,7 +178,7 @@ class Zoom::Profile < Hash
216
178
  ObjectSpace.each_object(Class).select do |clas|
217
179
  if (clas < self)
218
180
  begin
219
- clas.new(clas.to_s)
181
+ clas.new
220
182
  true
221
183
  rescue Zoom::Error::ExecutableNotFound
222
184
  false
@@ -232,17 +194,27 @@ class Zoom::Profile < Hash
232
194
  ret.push(hilight_name)
233
195
  ret.push("#{hilight_class}\n")
234
196
  ret.push(hilight_before(before)) if (!before.empty?)
235
- ret.push(hilight_operator(operator)) if (!operator.empty?)
197
+ ret.push(hilight_tool(tool)) if (!tool.empty?)
236
198
  ret.push(hilight_flags(flags)) if (!flags.empty?)
237
- if (@pattern.nil? || @pattern.empty?)
238
- ret.push(hilight_pattern("PATTERN"))
199
+ if (@regex.nil? || @regex.empty?)
200
+ ret.push(hilight_regex("REGEX"))
239
201
  else
240
- ret.push(hilight_pattern("\"#{@pattern}\""))
202
+ ret.push(hilight_regex("\"#{@regex}\""))
241
203
  end
242
204
  ret.push(hilight_after(after)) if (!after.empty?)
243
205
  return ret.join(" ").strip
244
206
  end
245
207
 
208
+ def tool(t = nil)
209
+ if (t)
210
+ t.strip!
211
+ tl = ScoobyDoo.where_are_you(t)
212
+ raise Zoom::Error::ExecutableNotFound.new(t) if (tl.nil?)
213
+ self["tool"] = t
214
+ end
215
+ return self["tool"]
216
+ end
217
+
246
218
  def translate(from)
247
219
  return ""
248
220
  end