|
| 1 | +import subprocess |
| 2 | + |
| 3 | + |
| 4 | +class Base: |
| 5 | + """ |
| 6 | + This is the base search engine class. |
| 7 | + Override it to define new search engines. |
| 8 | + """ |
| 9 | + |
| 10 | + SETTINGS = [ |
| 11 | + "path_to_executable", |
| 12 | + "mandatory_options", |
| 13 | + "common_options" |
| 14 | + ] |
| 15 | + |
| 16 | + def __init__(self, settings): |
| 17 | + """ |
| 18 | + Receives the sublime.Settings object |
| 19 | + """ |
| 20 | + self.settings = settings |
| 21 | + for setting_name in self.__class__.SETTINGS: |
| 22 | + setattr(self, setting_name, self.settings.get(self._full_settings_name(setting_name), '')) |
| 23 | + pass |
| 24 | + |
| 25 | + def run(self, query, folders): |
| 26 | + """ |
| 27 | + Run the search engine. Return a list of tuples, where first element is |
| 28 | + the absolute file path, and optionally row information, separated |
| 29 | + by a semicolon, and the second element is the result string |
| 30 | + """ |
| 31 | + command_line = self._command_line(query, folders) |
| 32 | + print("Running: %s" % command_line) |
| 33 | + pipe = subprocess.Popen(command_line, shell=True, stdout=subprocess.PIPE) |
| 34 | + output, error = pipe.communicate() |
| 35 | + if pipe.returncode != 0: |
| 36 | + raise Exception('Search engine returned error level: %s' % pipe.returncode, output, error) |
| 37 | + return self._parse_output(self._sanitize_output(output).strip()) |
| 38 | + |
| 39 | + def _command_line(self, query, folders): |
| 40 | + """ |
| 41 | + Prepare a command line for the search engine. |
| 42 | + """ |
| 43 | + return " ".join([ |
| 44 | + self.path_to_executable, |
| 45 | + self.mandatory_options, |
| 46 | + self.common_options, |
| 47 | + query |
| 48 | + ] + folders) |
| 49 | + |
| 50 | + def _sanitize_output(self, output): |
| 51 | + return unicode(output, errors='replace') |
| 52 | + |
| 53 | + def _parse_output(self, output): |
| 54 | + lines = output.split("\n") |
| 55 | + line_parts = [line.split(":", 2) for line in lines] |
| 56 | + line_parts = self._filter_lines_without_matches(line_parts) |
| 57 | + return [(":".join(line[0:-1]), line[-1].strip()) for line in line_parts] |
| 58 | + |
| 59 | + def _full_settings_name(self, name): |
| 60 | + return "search_in_project_%s_%s" % (self.__class__.__name__, name) |
| 61 | + |
| 62 | + def _filter_lines_without_matches(self, line_parts): |
| 63 | + return filter(lambda line: len(line) > 2, line_parts) |
0 commit comments