[meld] Move filter parsing and compilation logic from MeldApp to FilterEntry
- From: Kai Willadsen <kaiw src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [meld] Move filter parsing and compilation logic from MeldApp to FilterEntry
- Date: Tue, 15 Feb 2011 09:09:29 +0000 (UTC)
commit 39316bd3d63f6c0fc63c41b99b7fd3c915cf4655
Author: Kai Willadsen <kai willadsen gmail com>
Date: Fri Feb 11 18:47:42 2011 +1000
Move filter parsing and compilation logic from MeldApp to FilterEntry
In addition to making the code cleaner, this movement makes it somewhat
simpler to implement input validation for filter patterns in our
Preferences dialog.
meld/meldapp.py | 103 ++++++++++++++++++++++++++++++---------------------
meld/misc.py | 11 -----
meld/preferences.py | 16 +++++---
3 files changed, 71 insertions(+), 59 deletions(-)
---
diff --git a/meld/meldapp.py b/meld/meldapp.py
index 2de7b48..91df41d 100644
--- a/meld/meldapp.py
+++ b/meld/meldapp.py
@@ -32,15 +32,65 @@ version = "1.5.0"
class FilterEntry(object):
- __slots__ = ("label", "active", "filter")
+ __slots__ = ("label", "active", "filter", "filter_string")
- def __init__(self, label, active, filter):
+ REGEX, SHELL = 0, 1
+
+ def __init__(self, label, active, filter, filter_string):
self.label = label
self.active = active
self.filter = filter
+ self.filter_string = filter_string
+
+ @classmethod
+ def _compile_regex(cls, regex):
+ try:
+ compiled = re.compile(regex + "(?m)")
+ except re.error:
+ compiled = None
+ return compiled
+
+ @classmethod
+ def _compile_shell_pattern(cls, pattern):
+ bits = pattern.split()
+ if len(bits) > 1:
+ regexes = [misc.shell_to_regex(b)[:-1] for b in bits]
+ regex = "(%s)$" % "|".join(regexes)
+ elif len(bits):
+ regex = misc.shell_to_regex(bits[0])
+ else:
+ # An empty pattern would match everything, so skip it
+ return None
+
+ try:
+ compiled = re.compile(regex)
+ except re.error:
+ compiled = None
+
+ return compiled
+
+ @classmethod
+ def parse(cls, string, filter_type):
+ elements = string.split("\t")
+ name, active = elements[0], bool(int(elements[1]))
+ filter_string = " ".join(elements[2:])
+ compiled = FilterEntry.compile_filter(filter_string, filter_type)
+ if compiled is None:
+ active = False
+ return FilterEntry(name, active, compiled, filter_string)
+
+ @classmethod
+ def compile_filter(cls, filter_string, filter_type):
+ if filter_type == FilterEntry.REGEX:
+ compiled = FilterEntry._compile_regex(filter_string)
+ elif filter_type == FilterEntry.SHELL:
+ compiled = FilterEntry._compile_shell_pattern(filter_string)
+ else:
+ raise ValueError, "Unknown filter type"
+ return compiled
def __copy__(self):
- new = type(self)(self.label, self.active, None)
+ new = type(self)(self.label, self.active, None, self.filter_string)
if self.filter is not None:
new.filter = re.compile(self.filter.pattern, self.filter.flags)
return new
@@ -54,8 +104,10 @@ class MeldApp(object):
self.version = version
self.prefs = preferences.MeldPreferences()
self.prefs.notify_add(self.on_preference_changed)
- self.file_filters = self._update_filters(self.prefs.filters)
- self.text_filters = self._update_regexes(self.prefs.regexes)
+ self.file_filters = self._parse_filters(self.prefs.filters,
+ FilterEntry.SHELL)
+ self.text_filters = self._parse_filters(self.prefs.regexes,
+ FilterEntry.REGEX)
def create_window(self):
self.window = meldwindow.MeldWindow()
@@ -63,49 +115,16 @@ class MeldApp(object):
def on_preference_changed(self, key, val):
if key == "filters":
- self.file_filters = self._update_filters(val)
+ self.file_filters = self._parse_filters(val, FilterEntry.SHELL)
# FIXME: should emit a file-filters-changed signal here for
# DirDiff to respond to
elif key == "regexes":
- self.text_filters = self._update_regexes(val)
+ self.text_filters = self._parse_filters(val, FilterEntry.REGEX)
# FIXME: should emit a text-filters-changed signal here for
# FileDiff and DirDiff to respond to
- def _update_filters(self, filters_string):
- filters = []
- for filter_string in filters_string.split("\n"):
- elements = filter_string.split("\t")
- name, active = elements[0], bool(int(elements[1]))
- bits = (" ".join(elements[2:])).split()
- if len(bits) > 1:
- regexes = [misc.shell_to_regex(b)[:-1] for b in bits]
- regex = "(%s)$" % "|".join(regexes)
- elif len(bits):
- regex = misc.shell_to_regex(bits[0])
- else: # an empty pattern would match anything, skip it
- continue
- try:
- compiled = re.compile(regex)
- except re.error:
- active = False
- compiled = None
- filters.append(FilterEntry(name, active, compiled))
- return filters
-
- def _update_regexes(self, regexes_string):
- regexes = []
- for regex_string in regexes_string.split("\n"):
- elements = regex_string.split("\t")
- name, active = elements[0], bool(int(elements[1]))
- regex = " ".join(elements[2:])
- try:
- compiled = re.compile(regex + "(?m)")
- except re.error:
- active = False
- compiled = None
- regexes.append(FilterEntry(name, active, compiled))
- return regexes
-
+ def _parse_filters(self, string, filt_type):
+ return [FilterEntry.parse(l, filt_type) for l in string.split("\n")]
def diff_files_callback(self, option, opt_str, value, parser):
"""Gather --diff arguments and append to a list"""
diff --git a/meld/misc.py b/meld/misc.py
index 755bf6d..17fe275 100644
--- a/meld/misc.py
+++ b/meld/misc.py
@@ -350,14 +350,3 @@ def shell_to_regex(pat):
else:
res += re.escape(c)
return res + "$"
-
-class ListItem(object):
- __slots__ = ("name", "active", "value")
- def __init__(self, s):
- a = s.split("\t")
- self.name = a.pop(0)
- self.active = int(a.pop(0))
- self.value = " ".join(a)
- def __str__(self):
- return "<%s %s %i %s>" % ( self.__class__, self.name, self.active, self.value )
-
diff --git a/meld/preferences.py b/meld/preferences.py
index 1ac80fc..39cf691 100644
--- a/meld/preferences.py
+++ b/meld/preferences.py
@@ -21,6 +21,7 @@ import gtk
from ui import gnomeglade
from ui import listwidget
+import meldapp
import misc
import paths
from util import prefs
@@ -31,14 +32,15 @@ from util.sourceviewer import srcviewer
class FilterList(listwidget.ListWidget):
- def __init__(self, prefs, key):
- listwidget.ListWidget.__init__(self, [_("label"), 0, _("pattern")])
+ def __init__(self, prefs, key, filter_type):
+ default_entry = [_("label"), False, _("pattern")]
+ listwidget.ListWidget.__init__(self, default_entry)
self.prefs = prefs
self.key = key
for filtstring in getattr(self.prefs, self.key).split("\n"):
- filt = misc.ListItem(filtstring)
- self.model.append([filt.name, filt.active, filt.value])
+ filt = meldapp.FilterEntry.parse(filtstring, filter_type)
+ self.model.append([filt.label, filt.active, filt.filter_string])
for signal in ('row-changed', 'row-deleted', 'row-inserted',
'rows-reordered'):
@@ -110,12 +112,14 @@ class PreferencesDialog(gnomeglade.Component):
self.custom_edit_command_entry.set_text( " ".join(self.prefs.get_custom_editor_command([])) )
# file filters
- self.filefilter = FilterList(self.prefs, "filters")
+ self.filefilter = FilterList(self.prefs, "filters",
+ meldapp.FilterEntry.SHELL)
self.file_filters_tab.pack_start(self.filefilter.widget)
self.checkbutton_ignore_symlinks.set_active( self.prefs.ignore_symlinks)
# text filters
- self.textfilter = FilterList(self.prefs, "regexes")
+ self.textfilter = FilterList(self.prefs, "regexes",
+ meldapp.FilterEntry.REGEX)
self.text_filters_tab.pack_start(self.textfilter.widget)
self.checkbutton_ignore_blank_lines.set_active( self.prefs.ignore_blank_lines )
# encoding
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]