ruby-zoom 4.7.5 → 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
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