-
Notifications
You must be signed in to change notification settings - Fork 0
/
filter.py
98 lines (83 loc) · 4.08 KB
/
filter.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
import functools
import itertools
import re
import sublime
import sublime_plugin
settings_path = 'Filter Lines.sublime-settings'
class PromptFilterToLinesCommand(sublime_plugin.WindowCommand):
def run(self, search_type='string'):
self._run(search_type, "filter_to_lines", "Filter")
def _run(self, search_type, filter_command, filter_verb):
self.load_settings()
self.filter_command = filter_command
self.search_type = search_type
if search_type == 'string':
prompt = "%s to lines %s: " % (filter_verb, 'containing')
self.invert_search = False
elif search_type == 'string_invert':
prompt = "%s to lines %s: " % (filter_verb, 'not containing')
self.invert_search = True
elif search_type == 'regex_invert':
prompt = "%s to lines %s: " % (filter_verb, 'not matching')
self.invert_search = True
else:
prompt = "%s to lines %s: " % (filter_verb, 'matching')
self.invert_search = False
sublime.active_window().show_input_panel(prompt, self.search_text, self.on_search_text_entered, None, None)
def on_search_text_entered(self, search_text):
self.search_text = search_text
self.save_settings()
if self.window.active_view():
self.window.active_view().run_command(self.filter_command, {
"needle": self.search_text, "search_type": self.search_type})
def load_settings(self):
self.settings = sublime.load_settings(settings_path)
self.search_text = ""
if self.settings.get('preserve_search', True):
self.search_text = self.settings.get('latest_search', '')
def save_settings(self):
if self.settings.get('preserve_search', True):
self.settings.set('latest_search', self.search_text)
class FilterToLinesCommand(sublime_plugin.TextCommand):
def run(self, edit, needle, search_type):
settings = sublime.load_settings(settings_path)
flags = self.get_search_flags(search_type, settings)
lines = itertools.groupby(self.view.find_all(needle, flags), self.view.line)
self.line_numbers = settings.get('line_numbers', False)
self.show_filtered_lines(edit, lines)
def get_search_flags(self, search_type, settings):
flags = 0
if search_type == 'string':
flags = sublime.LITERAL
if not settings.get('case_sensitive_string_search', False):
flags = flags | sublime.IGNORECASE
elif search_type == 'regex':
if not settings.get('case_sensitive_string_search', False):
flags = sublime.IGNORECASE
return flags
def show_filtered_lines(self, edit, lines):
results_view = self.view.window().new_file()
results_view.set_name('Filter Results')
results_view.set_scratch(True)
results_view.settings().set('word_wrap', self.view.settings().get('word_wrap'))
if self.invert_search:
source_lines = self.view.lines(sublime.Region(0, self.view.size()))
filtered_line_numbers = [self.view.rowcol(line.begin())[0] for line, _ in lines]
for line_number in reversed(filtered_line_numbers):
del source_lines[line_number]
text = ''
for line in source_lines:
text += self.prepare_output_line(line, None)
results_view.run_command('append', {'characters': text, 'force': True, 'scroll_to_end': False})
else:
text = ''
for line, matches in lines:
text += self.prepare_output_line(line, matches)
results_view.run_command('append', {'characters': text, 'force': True, 'scroll_to_end': False})
results_view.set_syntax_file(self.view.settings().get('syntax'))
def prepare_output_line(self, line, matches):
if self.line_numbers and not self.invert_search:
line_number = self.view.rowcol(line.begin())[0]
return '%5d: %s\n' % (line_number, self.view.substr(line))
else:
return '%s\n' % (self.view.substr(line))