Also, you have a typo in method "desactivate" it should be "deactivate"
From: lee_connell hotmail com
To: olauzanne gmail com; gedit-list gnome org
Date: Mon, 30 Jun 2008 22:31:40 -0400
Subject: Re: [gedit-list] Smart indentation for python code
This plugin works well, i created a .gedit-plugin file required to load this plugin into gedit. I can't seem to reproduce the undo error. I wrote a script and then ran through a bunch of undo's to try to reproduce with no results. any specific way to reproduce it? BTW: great plugin, this is something really needed for python editing with gedit. thanks!
-Lee
Date: Wed, 25 Jun 2008 20:49:38 +0200
From: olauzanne gmail com
To: gedit-list gnome org
Subject: [gedit-list] Smart indentation for python code
Hello !
I made a gedit pluging to add a smart indentation while writing python conde:
The code is indented when the previous line ends with ':' and un-indented if
the previous line starts with 'return', 'pass', 'continue' or 'break'. This
plugin will use your tab configuration for indentation. To respect PEP8 you
should set tab width to 4 and choose to insert spaces instead of tabs.
It works alright except for a random bug with undos that sometimes don't work.
(gedit:7878): GtkSourceView-CRITICAL **: gtk_source_undo_manager_modified_changed_handler: assertion `action != NULL' failed
(gedit:7878): GtkSourceView-CRITICAL **: gtk_source_undo_manager_undo: assertion `undo_action != NULL' failed
Any of you have an idea where it comes from ?
Here is the source code of my plugin.
# -*- coding: utf-8 -*-
# Copyright (C) 2008 - Olivier Lauzanne
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""Gedit Plugin : smart indentation for python code
The code is indented when the previous line ends with ':' and un-indented if
the previous line starts with 'return', 'pass', 'continue' or 'break'. This
plugin will use your tab configuration for indentation. To respect PEP8 you
should set tab width to 4 and choose to insert spaces instead of tabs.
TODO : UNDO BUG
"""
from gtk import gdk
import gedit
class Plugin(gedit.Plugin):
"""The python indentation plugin"""
def activate(self, window):
self.views = {}
def desactivate(self, window):
"""Disconnect all signals.
"""
for view, signal in self.views.items():
view.disconnect(signal)
def update_ui(self, window):
"""Connect the key-press-event signal of the current view to the
on_key_press method.
"""
buffer = window.get_active_document()
view = window.get_active_view()
if buffer == None or view == None:
return
language = buffer.get_language()
if language == None:
return
if language.get_name() == 'Python' and view not in self.views:
self.views[view] = (view.connect('key-press-event',
self.on_key_press, buffer))
def on_key_press(self, view, event, buffer):
"""Check if the key press is 'Return' or 'Backspace' and indent or
un-indent accordingly.
"""
key_name = gdk.keyval_name(event.keyval)
if key_name not in ('Return', 'Backspace') or \
len(buffer.get_selection_bounds()) != 0:
# If some text is selected we want the default behavior of Return
# and Backspace so we do nothing
return
if view.get_insert_spaces_instead_of_tabs():
self.indent = ' ' * view.props.tab_width
else:
self.indent = '\t'
if key_name == 'Return':
line = self._get_current_line(buffer)
if line.endswith(':'):
old_indent = line[:len(line) - len(line.lstrip())]
buffer.insert_at_cursor('\n' + old_indent + self.indent)
return True
else:
stripped_line = line.strip()
n = len(line) - len(line.lstrip())
if (stripped_line.startswith('return')
or stripped_line.startswith('break')
or stripped_line.startswith('continue')
or stripped_line.startswith('pass')):
n -= len(self.indent)
buffer.insert_at_cursor('\n' + line[:n])
self._scroll_to_cursor(buffer, view)
return True
if key_name == 'BackSpace':
line = self._get_current_line(buffer)
if line.strip() == '' and line != '':
length = len(self.indent)
nb_to_delete = len(line) % length or length
self._delete_before_cursor(buffer, nb_to_delete)
self._scroll_to_cursor(buffer, view)
return True
def _delete_before_cursor(self, buffer, nb_to_delete):
cursor_position = buffer.get_property('cursor-position')
iter_cursor = buffer.get_iter_at_offset(cursor_position)
iter_before = buffer.get_iter_at_offset(cursor_position - nb_to_delete)
buffer.delete(iter_before, iter_cursor)
def _get_current_line(self, buffer):
iter_cursor = self._get_iter_cursor(buffer)
iter_line = buffer.get_iter_at_line(iter_cursor.get_line())
return buffer.get_text(iter_line, iter_cursor)
def _get_current_line_nb(self, buffer):
iter_cursor = self._get_iter_cursor(buffer)
return iter_cursor.get_line()
def _get_iter_cursor(self, buffer):
cursor_position = buffer.get_property('cursor-position')
return buffer.get_iter_at_offset(cursor_position)
def _scroll_to_cursor(self, buffer, view):
lineno = self._get_current_line_nb(buffer) + 1
insert = buffer.get_insert()
view.scroll_mark_onscreen(insert)
The i'm Talkathon starts 6/24/08. For now, give amongst yourselves. Learn More
Making the world a better place one message at a time. Check out the i'm Talkathon.
# -*- coding: utf-8 -*- # Copyright (C) 2008 - Olivier Lauzanne # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. """Gedit Plugin : smart indentation for python code The code is indented when the previous line ends with ':' and un-indented if the previous line starts with 'return', 'pass', 'continue' or 'break'. This plugin will use your tab configuration for indentation. To respect PEP8 you should set tab width to 4 and choose to insert spaces instead of tabs. TODO : UNDO BUG """ from gtk import gdk import gedit class Plugin(gedit.Plugin): """The python indentation plugin""" def activate(self, window): self.views = {} def deactivate(self, window): """Disconnect all signals. """ for view, signal in self.views.items(): view.disconnect(signal) def update_ui(self, window): """Connect the key-press-event signal of the current view to the on_key_press method if we are editing a python file. """ buffer = window.get_active_document() view = window.get_active_view() if buffer == None or view == None: return language = buffer.get_language() if language == None: return if language.get_name() == 'Python' and view not in self.views: self.views[view] = (view.connect('key-press-event', self.on_key_press, buffer)) def on_key_press(self, view, event, buffer): """Check if the key press is 'Return' or 'Backspace' and indent or un-indent accordingly. """ key_name = gdk.keyval_name(event.keyval) if key_name not in ('Return', 'BackSpace') or \ len(buffer.get_selection_bounds()) != 0: # If some text is selected we want the default behavior of Return # and Backspace so we do nothing return if view.get_insert_spaces_instead_of_tabs(): self.indent = ' ' * view.props.tab_width else: self.indent = '\t' if key_name == 'Return': line = self._get_current_line(buffer) if line.endswith(':'): old_indent = line[:len(line) - len(line.lstrip())] buffer.insert_at_cursor('\n' + old_indent + self.indent) return True else: stripped_line = line.strip() n = len(line) - len(line.lstrip()) if (stripped_line.startswith('return') or stripped_line.startswith('break') or stripped_line.startswith('continue') or stripped_line.startswith('pass')): n -= len(self.indent) buffer.insert_at_cursor('\n' + line[:n]) self._scroll_to_cursor(buffer, view) return True if key_name == 'BackSpace': line = self._get_current_line(buffer) if line.strip() == '' and line != '': length = len(self.indent) nb_to_delete = len(line) % length or length self._delete_before_cursor(buffer, nb_to_delete) self._scroll_to_cursor(buffer, view) return True def _delete_before_cursor(self, buffer, nb_to_delete): cursor_position = buffer.get_property('cursor-position') iter_cursor = buffer.get_iter_at_offset(cursor_position) iter_before = buffer.get_iter_at_offset(cursor_position - nb_to_delete) buffer.delete(iter_before, iter_cursor) def _get_current_line(self, buffer): iter_cursor = self._get_iter_cursor(buffer) iter_line = buffer.get_iter_at_line(iter_cursor.get_line()) return buffer.get_text(iter_line, iter_cursor) def _get_current_line_nb(self, buffer): iter_cursor = self._get_iter_cursor(buffer) return iter_cursor.get_line() def _get_iter_cursor(self, buffer): cursor_position = buffer.get_property('cursor-position') return buffer.get_iter_at_offset(cursor_position) def _scroll_to_cursor(self, buffer, view): lineno = self._get_current_line_nb(buffer) + 1 insert = buffer.get_insert() view.scroll_mark_onscreen(insert)
Attachment:
python_indentation.gedit-plugin
Description: Binary data