gedit r6793 - in trunk: . plugins/snippets/snippets
- From: jessevdk svn gnome org
- To: svn-commits-list gnome org
- Subject: gedit r6793 - in trunk: . plugins/snippets/snippets
- Date: Fri, 2 Jan 2009 14:37:55 +0000 (UTC)
Author: jessevdk
Date: Fri Jan 2 14:37:54 2009
New Revision: 6793
URL: http://svn.gnome.org/viewvc/gedit?rev=6793&view=rev
Log:
* plugins/snippets/snippets/Document.py:
* plugins/snippets/snippets/Helper.py:
* plugins/snippets/snippets/Placeholder.py:
* plugins/snippets/snippets/Snippet.py:
Implemented support for 'hugging' placeholders
(e.g. ${1:text}${2:text})
Modified:
trunk/ChangeLog
trunk/plugins/snippets/snippets/Document.py
trunk/plugins/snippets/snippets/Helper.py
trunk/plugins/snippets/snippets/Placeholder.py
trunk/plugins/snippets/snippets/Snippet.py
Modified: trunk/plugins/snippets/snippets/Document.py
==============================================================================
--- trunk/plugins/snippets/snippets/Document.py (original)
+++ trunk/plugins/snippets/snippets/Document.py Fri Jan 2 14:37:54 2009
@@ -42,6 +42,7 @@
self.active_placeholder = None
self.signal_ids = {}
+ self.ordered_placeholders = []
self.update_placeholders = []
self.jump_placeholders = []
self.language_id = 0
@@ -74,6 +75,10 @@
def connect_signal(self, obj, signal, cb):
self.disconnect_signal(obj, signal)
self.signal_ids[(obj, signal)] = obj.connect(signal, cb)
+
+ def connect_signal_after(self, obj, signal, cb):
+ self.disconnect_signal(obj, signal)
+ self.signal_ids[(obj, signal)] = obj.connect_after(signal, cb)
# Set the view to be controlled. Installs signal handlers and sets current
# language. If there is already a view set this function will first remove
@@ -87,7 +92,7 @@
# Remove signals
signals = {self.view: ('key-press-event', 'destroy',
'notify::editable', 'drag-data-received'),
- buf: ('notify::language', 'changed', 'cursor-moved')}
+ buf: ('notify::language', 'changed', 'cursor-moved', 'insert-text')}
for obj, sig in signals.items():
for s in sig:
@@ -178,67 +183,97 @@
self.connect_signal(buf, 'changed', self.on_buffer_changed)
self.connect_signal(buf, 'cursor-moved', self.on_buffer_cursor_moved)
+ self.connect_signal_after(buf, 'insert-text', self.on_buffer_insert_text)
def last_snippet_removed(self):
buf = self.view.get_buffer()
self.disconnect_signal(buf, 'changed')
self.disconnect_signal(buf, 'cursor-moved')
+ self.disconnect_signal(buf, 'insert-text')
def current_placeholder(self):
buf = self.view.get_buffer()
piter = buf.get_iter_at_mark(buf.get_insert())
- current = None
+ found = []
for placeholder in self.placeholders:
begin = placeholder.begin_iter()
end = placeholder.end_iter()
- if piter.compare(begin) >= 0 and \
- piter.compare(end) <= 0:
- current = placeholder
+ if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
+ found.append(placeholder)
- return current
+ if self.active_placeholder in found:
+ return self.active_placeholder
+ elif len(found) > 0:
+ return found[0]
+ else:
+ return None
def advance_placeholder(self, direction):
# Returns (CurrentPlaceholder, NextPlaceholder), depending on direction
buf = self.view.get_buffer()
piter = buf.get_iter_at_mark(buf.get_insert())
- prev = current = next = None
- length = len(self.placeholders)
+ found = current = next = None
+ length = len(self.placeholders)
+
+ placeholders = list(self.placeholders)
+
+ if self.active_placeholder:
+ begin = self.active_placeholder.begin_iter()
+ end = self.active_placeholder.end_iter()
+
+ if piter.compare(begin) >= 0 and piter.compare(end) <= 0:
+ current = self.active_placeholder
+ currentIndex = placeholders.index(self.active_placeholder)
if direction == 1:
- nearest = lambda w, x, y, z: (w.compare(y) >= 0 and (not z or \
- y.compare(z.end_iter()) >= 0))
+ # w = piter, x = begin, y = end, z = found
+ nearest = lambda w, x, y, z: (w.compare(x) <= 0 and (not z or \
+ x.compare(z.begin_iter()) < 0))
indexer = lambda x: x < length - 1
else:
- nearest = lambda w, x, y, z: (w.compare(x) <= 0 and (not z or \
- x.compare(z.end_iter()) <= 0))
+ # w = piter, x = begin, y = end, z = prev
+ nearest = lambda w, x, y, z: (w.compare(x) >= 0 and (not z or \
+ x.compare(z.begin_iter()) >= 0))
indexer = lambda x: x > 0
for index in range(0, length):
- placeholder = self.placeholders[index]
+ placeholder = placeholders[index]
begin = placeholder.begin_iter()
end = placeholder.end_iter()
# Find the nearest placeholder
- if nearest(piter, begin, end, prev):
- prevIndex = index
- prev = placeholder
+ if nearest(piter, begin, end, found):
+ foundIndex = index
+ found = placeholder
# Find the current placeholder
if piter.compare(begin) >= 0 and \
- piter.compare(end) <= 0:
+ piter.compare(end) <= 0 and \
+ current == None:
currentIndex = index
current = placeholder
- if current:
+ if current and current != found and \
+ (current.begin_iter().compare(found.begin_iter()) == 0 or \
+ current.end_iter().compare(found.begin_iter()) == 0) and \
+ self.active_placeholder and \
+ current.begin_iter().compare(self.active_placeholder.begin_iter()) == 0:
+ # if current and found are at the same place, then
+ # resolve the 'hugging' problem
+ current = self.active_placeholder
+ currentIndex = placeholders.index(current)
+
+ found = current
+
+ if current and current == found:
if indexer(currentIndex):
- next = self.placeholders[currentIndex + direction]
- elif prev:
- if indexer(prevIndex):
- next = self.placeholders[prevIndex + direction]
+ next = placeholders[currentIndex + direction]
+ elif found:
+ next = found
elif length > 0:
next = self.placeholders[0]
@@ -254,6 +289,9 @@
buf = self.view.get_buffer()
self.view.scroll_mark_onscreen(buf.get_insert())
+ def set_active_placeholder(self, placeholder):
+ self.active_placeholder = placeholder
+
def goto_placeholder(self, current, next):
last = None
@@ -264,7 +302,7 @@
if current.__class__ == PlaceholderEnd:
last = current
- self.active_placeholder = next
+ self.set_active_placeholder(next)
if next:
next.enter()
@@ -275,7 +313,7 @@
if last:
# This is the end of the placeholder, remove the snippet etc
for snippet in list(self.active_snippets):
- if snippet[3][0] == last:
+ if snippet.placeholders[0] == last:
self.deactivate_snippet(snippet)
break
@@ -374,25 +412,22 @@
# Insert the snippet
holders = len(self.placeholders)
- active_info = s.insert_into(self, start)
- self.active_snippets.append(active_info)
+
+ if len(self.active_snippets) == 0:
+ self.first_snippet_inserted()
- # Put cursor back to beginning of the snippet
- piter = buf.get_iter_at_mark(active_info[0])
- buf.place_cursor(piter)
+ sn = s.insert_into(self, start)
+ self.active_snippets.append(sn)
- # Jump to first placeholder
- (current, next) = self.next_placeholder()
+ # Put cursor at first tab placeholder
+ keys = filter(lambda x: x > 0, sn.placeholders.keys())
- if current and current != self.active_placeholder:
- self.goto_placeholder(None, current)
- elif next:
- self.goto_placeholder(None, next)
-
- buf.end_user_action()
+ if len(keys) == 0:
+ buf.place_cursor(sn.begin_iter())
+ else:
+ self.goto_placeholder(self.active_placeholder, sn.placeholders[keys[0]])
- if len(self.active_snippets) == 1:
- self.first_snippet_inserted()
+ buf.end_user_action()
return True
@@ -452,11 +487,11 @@
buf = self.view.get_buffer()
remove = []
- for tabstop in snippet[3]:
+ for tabstop in snippet.placeholders:
if tabstop == -1:
- placeholders = snippet[3][-1]
+ placeholders = snippet.placeholders[-1]
else:
- placeholders = [snippet[3][tabstop]]
+ placeholders = [snippet.placeholders[tabstop]]
for placeholder in placeholders:
if placeholder in self.placeholders:
@@ -474,12 +509,11 @@
self.active_placeholder = None
self.placeholders.remove(placeholder)
+ self.ordered_placeholders.remove(placeholder)
+
placeholder.remove(force)
- buf.delete_mark(snippet[0])
- buf.delete_mark(snippet[1])
- buf.delete_mark(snippet[2])
-
+ snippet.deactivate()
self.active_snippets.remove(snippet)
if len(self.active_snippets) == 0:
@@ -600,11 +634,11 @@
# Check for all snippets if the cursor is outside its scope
for snippet in list(self.active_snippets):
- if snippet[0].get_deleted() or snippet[1].get_deleted():
+ if snippet.begin_mark.get_deleted() or snippet.end_mark.get_deleted():
self.deactivate(snippet)
else:
- begin = buf.get_iter_at_mark(snippet[0])
- end = buf.get_iter_at_mark(snippet[1])
+ begin = snippet.begin_iter()
+ end = snippet.end_iter()
if piter.compare(begin) < 0 or piter.compare(end) > 0:
# Oh no! Remove the snippet this instant!!
@@ -616,13 +650,11 @@
if self.active_placeholder:
self.jump_placeholders.append((self.active_placeholder, current))
- if self.timeout_update_id != 0:
- gobject.source_remove(self.timeout_update_id)
-
- self.timeout_update_id = gobject.timeout_add(0,
- self.update_snippet_contents)
+ if self.timeout_update_id == 0:
+ self.timeout_update_id = gobject.timeout_add(0,
+ self.update_snippet_contents)
- self.active_placeholder = current
+ self.set_active_placeholder(current)
def on_buffer_changed(self, buf):
current = self.current_placeholder()
@@ -631,11 +663,48 @@
if not current in self.update_placeholders:
self.update_placeholders.append(current)
- if self.timeout_update_id != 0:
- gobject.source_remove(self.timeout_update_id)
-
- self.timeout_update_id = gobject.timeout_add(0, \
- self.update_snippet_contents)
+ if self.timeout_update_id == 0:
+ self.timeout_update_id = gobject.timeout_add(0, \
+ self.update_snippet_contents)
+
+ def on_buffer_insert_text(self, buf, piter, text, length):
+ ctx = get_buffer_context(buf)
+
+ # do nothing special if there is no context and no active
+ # placeholder
+ if (not ctx) and (not self.active_placeholder):
+ return
+
+ if not ctx:
+ ctx = self.active_placeholder
+
+ if not ctx in self.ordered_placeholders:
+ return
+
+ # move any marks that were incorrectly moved by this insertion
+ # back to where they belong
+ begin = ctx.begin_iter()
+ end = ctx.end_iter()
+ idx = self.ordered_placeholders.index(ctx)
+
+ for placeholder in self.ordered_placeholders:
+ if placeholder == ctx:
+ continue
+
+ ob = placeholder.begin_iter()
+ oe = placeholder.end_iter()
+
+ if ob.compare(begin) == 0 and ((not oe) or oe.compare(end) == 0):
+ oidx = self.ordered_placeholders.index(placeholder)
+
+ if oidx > idx and ob:
+ buf.move_mark(placeholder.begin, end)
+ elif oidx < idx and oe:
+ buf.move_mark(placeholder.end, begin)
+ elif ob.compare(begin) >= 0 and ob.compare(end) < 0 and (oe and oe.compare(end) >= 0):
+ buf.move_mark(placeholder.begin, end)
+ elif (oe and oe.compare(begin) > 0) and ob.compare(begin) <= 0:
+ buf.move_mark(placeholder.end, begin)
def on_notify_language(self, buf, spec):
self.update_language()
Modified: trunk/plugins/snippets/snippets/Helper.py
==============================================================================
--- trunk/plugins/snippets/snippets/Helper.py (original)
+++ trunk/plugins/snippets/snippets/Helper.py Fri Jan 2 14:37:54 2009
@@ -58,10 +58,12 @@
return text.replace("\t", view.get_tab_width() * ' ')
-def insert_with_indent(view, piter, text, indentfirst = True):
+def insert_with_indent(view, piter, text, indentfirst = True, context = None):
text = spaces_instead_of_tabs(view, text)
lines = text.split('\n')
+ view.get_buffer().set_data('GeditSnippetsPluginContext', context)
+
if len(lines) == 1:
view.get_buffer().insert(piter, text)
else:
@@ -77,6 +79,11 @@
view.get_buffer().insert(piter, text[:-1])
+ view.get_buffer().set_data('GeditSnippetsPluginContext', None)
+
+def get_buffer_context(buf):
+ return buf.get_data('GeditSnippetsPluginContext')
+
def snippets_debug(*s):
return
@@ -182,4 +189,5 @@
result.append(line)
return result
+
# ex:ts=8:et:
Modified: trunk/plugins/snippets/snippets/Placeholder.py
==============================================================================
--- trunk/plugins/snippets/snippets/Placeholder.py (original)
+++ trunk/plugins/snippets/snippets/Placeholder.py Fri Jan 2 14:37:54 2009
@@ -41,14 +41,21 @@
self.tabstop = tabstop
self.set_default(defaults)
self.prev_contents = self.default
+ self.set_mark_gravity()
if begin:
- self.begin = self.buf.create_mark(None, begin, True)
+ self.begin = self.buf.create_mark(None, begin, self.mark_gravity[0])
else:
self.begin = None
self.end = None
+ def __str__(self):
+ return '%s (%s)' % (str(self.__class__), str(self.default))
+
+ def set_mark_gravity(self):
+ self.mark_gravity = [True, False]
+
def set_default(self, defaults):
if not defaults:
self.default = None
@@ -95,10 +102,10 @@
def run_last(self, placeholders):
begin = self.begin_iter()
- self.end = self.buf.create_mark(None, begin, False)
-
+ self.end = self.buf.create_mark(None, begin, self.mark_gravity[1])
+
if self.default:
- insert_with_indent(self.view, begin, self.default, False)
+ insert_with_indent(self.view, begin, self.default, False, self)
def remove(self, force = False):
if self.begin and not self.begin.get_deleted():
@@ -150,7 +157,7 @@
self.buf.delete(begin, self.end_iter())
# Insert the text from the mirror
- insert_with_indent(self.view, begin, text, True)
+ insert_with_indent(self.view, begin, text, True, self)
self.buf.end_user_action()
self.update_contents()
@@ -234,8 +241,9 @@
# any text
if not self.default:
+ self.mark_gravity[0] = False
self.buf.delete_mark(self.begin)
- self.begin = self.buf.create_mark(None, self.end_iter(), False)
+ self.begin = self.buf.create_mark(None, self.end_iter(), self.mark_gravity[0])
def enter(self):
if self.begin and not self.begin.get_deleted():
Modified: trunk/plugins/snippets/snippets/Snippet.py
==============================================================================
--- trunk/plugins/snippets/snippets/Snippet.py (original)
+++ trunk/plugins/snippets/snippets/Snippet.py Fri Jan 2 14:37:54 2009
@@ -136,27 +136,30 @@
'</b>)'
def _add_placeholder(self, placeholder):
- if placeholder.tabstop in self._placeholders:
+ if placeholder.tabstop in self.placeholders:
if placeholder.tabstop == -1:
- self._placeholders[-1].append(placeholder)
+ self.placeholders[-1].append(placeholder)
+ self.plugin_data.ordered_placeholders.append(placeholder)
elif placeholder.tabstop == -1:
- self._placeholders[-1] = [placeholder]
+ self.placeholders[-1] = [placeholder]
+ self.plugin_data.ordered_placeholders.append(placeholder)
else:
- self._placeholders[placeholder.tabstop] = placeholder
+ self.placeholders[placeholder.tabstop] = placeholder
+ self.plugin_data.ordered_placeholders.append(placeholder)
def _insert_text(self, text):
# Insert text keeping indentation in mind
indented = unicode.join('\n' + unicode(self._indent), spaces_instead_of_tabs(self._view, text).split('\n'))
- self._view.get_buffer().insert(self._begin_iter(), indented)
+ self._view.get_buffer().insert(self._insert_iter(), indented)
- def _begin_iter(self):
- return self._view.get_buffer().get_iter_at_mark(self._begin_mark)
+ def _insert_iter(self):
+ return self._view.get_buffer().get_iter_at_mark(self._insert_mark)
def _create_environment(self, data):
val = ((data in os.environ) and os.environ[data]) or ''
# Get all the current indentation
- all_indent = compute_indentation(self._view, self._begin_iter())
+ all_indent = compute_indentation(self._view, self._insert_iter())
# Substract initial indentation to get the snippet indentation
indent = all_indent[len(self._indent):]
@@ -166,12 +169,12 @@
def _create_placeholder(self, data):
tabstop = data['tabstop']
- begin = self._begin_iter()
+ begin = self._insert_iter()
if tabstop == 0:
# End placeholder
return PlaceholderEnd(self._view, begin, data['default'])
- elif tabstop in self._placeholders:
+ elif tabstop in self.placeholders:
# Mirror placeholder
return PlaceholderMirror(self._view, tabstop, begin)
else:
@@ -179,15 +182,15 @@
return Placeholder(self._view, tabstop, data['default'], begin)
def _create_shell(self, data):
- begin = self._begin_iter()
+ begin = self._insert_iter()
return PlaceholderShell(self._view, data['tabstop'], begin, data['contents'])
def _create_eval(self, data):
- begin = self._begin_iter()
+ begin = self._insert_iter()
return PlaceholderEval(self._view, data['tabstop'], data['dependencies'], begin, data['contents'], self._utils.namespace)
def _create_regex(self, data):
- begin = self._begin_iter()
+ begin = self._insert_iter()
return PlaceholderRegex(self._view, data['tabstop'], begin, data['input'], data['pattern'], data['substitution'], data['modifiers'])
def _create_text(self, data):
@@ -203,18 +206,21 @@
placeholder.remove()
if placeholder.tabstop == -1:
- index = self._placeholders[-1].index(placeholder)
- del self._placeholders[-1][index]
+ index = self.placeholders[-1].index(placeholder)
+ del self.placeholders[-1][index]
else:
- del self._placeholders[placeholder.tabstop]
+ del self.placeholders[placeholder.tabstop]
+
+ self.plugin_data.ordered_placeholders.remove(placeholder)
- def _parse(self, view, marks):
+ def _parse(self, plugin_data):
# Initialize current variables
- self._view = view
- self._indent = compute_indentation(view, view.get_buffer().get_iter_at_mark(marks[1]))
- self._utils = EvalUtilities(view)
- self._placeholders = {}
- self._begin_mark = marks[1]
+ self._view = plugin_data.view
+ self._indent = compute_indentation(self._view, self._view.get_buffer().get_iter_at_mark(self.begin_mark))
+ self._utils = EvalUtilities(self._view)
+ self.placeholders = {}
+ self._insert_mark = self.end_mark
+ self.plugin_data = plugin_data
# Create parser
parser = Parser(data=self['text'])
@@ -245,16 +251,17 @@
self._add_placeholder(val)
# Create end placeholder if there isn't one yet
- if 0 not in self._placeholders:
- self._placeholders[0] = PlaceholderEnd(view, view.get_buffer().get_iter_at_mark(marks[1]), None)
+ if 0 not in self.placeholders:
+ self.placeholders[0] = PlaceholderEnd(self._view, self.end_iter(), None)
+ self.plugin_data.ordered_placeholders.append(self.placeholders[0])
# Make sure run_last is ran for all placeholders and remove any
# non `ok` placeholders
- for tabstop in self._placeholders.copy():
- ph = (tabstop == -1 and list(self._placeholders[-1])) or [self._placeholders[tabstop]]
+ for tabstop in self.placeholders.copy():
+ ph = (tabstop == -1 and list(self.placeholders[-1])) or [self.placeholders[tabstop]]
for placeholder in ph:
- placeholder.run_last(self._placeholders)
+ placeholder.run_last(self.placeholders)
if not placeholder.ok or placeholder.done:
self._invalid_placeholder(placeholder, not placeholder.ok)
@@ -263,20 +270,22 @@
# they can be used to mirror, but they shouldn't be real tabstops
# (if they have mirrors installed). This is problably a bit of
# a dirty hack :)
- if -1 not in self._placeholders:
- self._placeholders[-1] = []
+ if -1 not in self.placeholders:
+ self.placeholders[-1] = []
- for tabstop in self._placeholders.copy():
- placeholder = self._placeholders[tabstop]
+ for tabstop in self.placeholders.copy():
+ placeholder = self.placeholders[tabstop]
if tabstop != -1:
if isinstance(placeholder, PlaceholderExpand) and placeholder.has_references:
# Add to anonymous placeholders
- self._placeholders[-1].append(placeholder)
+ self.placeholders[-1].append(placeholder)
# Remove placeholder
- del self._placeholders[tabstop]
+ del self.placeholders[tabstop]
+ self.plugin_data = None
+
def insert_into(self, plugin_data, insert):
buf = plugin_data.view.get_buffer()
last_index = 0
@@ -297,26 +306,25 @@
# lastIndex now contains the position of the last mark
# Create snippet bounding marks
- marks = (buf.create_mark(None, insert, True),
- buf.create_mark(None, insert, False),
- buf.create_mark(None, insert, False))
+ self.begin_mark = buf.create_mark(None, insert, True)
+ self.end_mark = buf.create_mark(None, insert, False)
# Now parse the contents of this snippet, create Placeholders
# and insert the placholder marks in the marks array of plugin_data
- self._parse(plugin_data.view, marks)
+ self._parse(plugin_data)
# So now all of the snippet is in the buffer, we have all our
# placeholders right here, what's next, put all marks in the
# plugin_data.marks
- k = self._placeholders.keys()
+ k = self.placeholders.keys()
k.sort(reverse=True)
- plugin_data.placeholders.insert(last_index, self._placeholders[0])
- last_iter = self._placeholders[0].end_iter()
+ plugin_data.placeholders.insert(last_index, self.placeholders[0])
+ last_iter = self.placeholders[0].end_iter()
for tabstop in k:
if tabstop != -1 and tabstop != 0:
- placeholder = self._placeholders[tabstop]
+ placeholder = self.placeholders[tabstop]
end_iter = placeholder.end_iter()
if last_iter.compare(end_iter) < 0:
@@ -326,8 +334,21 @@
plugin_data.placeholders.insert(last_index, placeholder)
# Move end mark to last placeholder
- buf.move_mark(marks[1], last_iter)
-
- return (marks[0], marks[1], marks[2], self._placeholders)
+ buf.move_mark(self.end_mark, last_iter)
+ return self
+
+ def deactivate(self):
+ buf = self.begin_mark.get_buffer()
+
+ buf.delete_mark(self.begin_mark)
+ buf.delete_mark(self.end_mark)
+
+ self.placeholders = {}
+
+ def begin_iter(self):
+ return self.begin_mark.get_buffer().get_iter_at_mark(self.begin_mark)
+
+ def end_iter(self):
+ return self.end_mark.get_buffer().get_iter_at_mark(self.end_mark)
# ex:ts=8:et:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]