[gedit-plugins] Implemented semantic replace



commit b7515a35c02b5f6bb07a02945128498225b044d2
Author: Jesse van den Kieboom <jesse vandenkieboom epfl ch>
Date:   Sun May 9 10:54:29 2010 +0200

    Implemented semantic replace

 plugins/commander/modules/find/__init__.py |    4 +-
 plugins/commander/modules/find/finder.py   |   16 ++++++-
 plugins/commander/modules/find/regex.py    |   76 +++++++++++++++++++++++++++-
 3 files changed, 91 insertions(+), 5 deletions(-)
---
diff --git a/plugins/commander/modules/find/__init__.py b/plugins/commander/modules/find/__init__.py
index c955004..1cff188 100644
--- a/plugins/commander/modules/find/__init__.py
+++ b/plugins/commander/modules/find/__init__.py
@@ -17,8 +17,8 @@ class TextFinder(finder.Finder):
 	def do_find(self, bounds):
 		buf = self.view.get_buffer()
 
-		if self.findstr:
-			buf.set_search_text(self.findstr, self.flags)
+		if self.get_find():
+			buf.set_search_text(self.get_find(), self.flags)
 
 		ret = map(lambda x: x.copy(), bounds)
 
diff --git a/plugins/commander/modules/find/finder.py b/plugins/commander/modules/find/finder.py
index 02d56a1..6e10941 100644
--- a/plugins/commander/modules/find/finder.py
+++ b/plugins/commander/modules/find/finder.py
@@ -46,6 +46,9 @@ class Finder:
 	def set_find(self, findstr):
 		self.findstr = self.unescape(findstr)
 
+	def get_find(self):
+		return self.findstr
+
 	def select_last_result(self):
 		buf = self.view.get_buffer()
 
@@ -204,6 +207,17 @@ class Finder:
 
 		self.view.scroll_to_mark(buf.get_insert(), 0.2, True, 0, 0.5)
 
+	def get_current_replace(self):
+		buf = self.view.get_buffer()
+		bounds = utils.Struct({'start': buf.get_iter_at_mark(self.find_result.start),
+		                       'end': buf.get_iter_at_mark(self.find_result.end)})
+
+		if not bounds.start.equal(bounds.end):
+			text = bounds.start.get_text(bounds.end)
+			return self.get_replace(text)
+		else:
+			return self.replacestr
+
 	def replace(self, findstr, replaceall=False, replacestr=None):
 		if findstr:
 			self.set_find(findstr)
@@ -247,7 +261,7 @@ class Finder:
 		try:
 			while True:
 				if not replaceall:
-					rep, words, modifier = (yield commands.result.Prompt('Replace next [%s]:' % (saxutils.escape(self.replacestr),)))
+					rep, words, modifier = (yield commands.result.Prompt('Replace next [%s]:' % (saxutils.escape(self.get_current_replace()),)))
 
 					if rep:
 						self.set_replace(rep)
diff --git a/plugins/commander/modules/find/regex.py b/plugins/commander/modules/find/regex.py
index ff15d2f..c1d45c5 100644
--- a/plugins/commander/modules/find/regex.py
+++ b/plugins/commander/modules/find/regex.py
@@ -79,6 +79,64 @@ class RegexFinder(finder.Finder):
 		except Exception, e:
 			raise commands.exceptions.Execute('Invalid replacement: ' + str(e))
 
+class SemanticFinder(RegexFinder):
+	def __init__(self, entry):
+		RegexFinder.__init__(self, entry, re.IGNORECASE)
+
+	def split_semantic(self, s):
+		# Can be specified in _ separated syntax, or in TitleCase
+		if '_' in s:
+			return s.lower().split('_')
+		else:
+			return [m.group(0).lower() for m in re.finditer('[A-Z]+([^A-Z]+)?', s)]
+
+	def set_find(self, findstr):
+		self.findparts = self.split_semantic(findstr)
+		RegexFinder.set_find(self, '(' + ')(_?)('.join(map(lambda x: re.escape(x), self.findparts)) + ')')
+
+	def set_replace(self, replstr):
+		self.replaceparts = self.split_semantic(replstr)
+		RegexFinder.set_replace(self, replstr)
+
+	def copy_case(self, orig, repl):
+		lo = len(orig)
+		lr = len(repl)
+
+		ret = ''
+
+		for i in range(min(lr, lo)):
+			if orig[i].isupper():
+				ret += repl[i].upper()
+			else:
+				ret += repl[i].lower()
+
+		if lr > lo:
+			if orig.isupper():
+				ret += repl[lo:].upper()
+			else:
+				ret += repl[lo:].lower()
+
+		return ret
+
+	def get_replace(self, text):
+		m = self.findre.match(text)
+		groups = m.groups()
+
+		ret = []
+
+		for i in range(len(groups)):
+			ri = i / 2
+
+			if i % 2 == 0:
+				if ri >= len(self.replaceparts):
+					break
+
+				ret.append(self.copy_case(groups[i], self.replaceparts[ri]))
+			else:
+				ret.append(groups[i])
+
+		return ''.join(ret)
+
 def __default__(entry, argstr):
 	"""Find regex in document: find.regex &lt;regex&gt;
 
@@ -110,15 +168,29 @@ Quickly find and replace phrases in the document using regular expressions"""
 	yield fd.replace(findre, False, replstr)
 
 def replace_all(entry, findre, replstr=None):
-	"""Find/replace all regex in document: find.replace-all &lt;find&gt; [&lt;replace&gt;]
+	"""Find/replace all regex in document: find.regex.replace-all &lt;find&gt; [&lt;replace&gt;]
 
 Quickly find and replace all phrases in the document using regular expressions"""
 	fd = RegexFinder(entry, 0)
 	yield fd.replace(findre, True, replstr)
 
 def replace_all_i(entry, findre, replstr=None):
-	"""Find/replace all regex in document: find.replace-all-i &lt;find&gt; [&lt;replace&gt;]
+	"""Find/replace all regex in document: find.regex.replace-all-i &lt;find&gt; [&lt;replace&gt;]
 
 Quickly find and replace all phrases in the document using regular expressions"""
 	fd = RegexFinder(entry, re.IGNORECASE)
 	yield fd.replace(findre, True, replstr)
+
+def replace_semantic(entry, findstr, replstr=None):
+	"""Find/replace in document (semantically): find.regex.replace-s &lt;find&gt; [&lt;replace&gt;]
+
+Find and replace semantically"""
+	fd = SemanticFinder(entry)
+	yield fd.replace(findstr, False, replstr)
+
+def replace_all_semantic(entry, findstr, replstr=None):
+	"""Find/replace in document (semantically): find.regex.replace-s &lt;find&gt; [&lt;replace&gt;]
+
+Find and replace semantically"""
+	fd = SemanticFinder(entry)
+	yield fd.replace(findstr, True, replstr)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]