# -*- coding: utf-8 -*- # Code comment plugin # This file is part of gedit # # Copyright (C) 2005-2006 Igalia # Copyright (C) 2006 Matthew Dugan # Copyrignt (C) 2007 Steve Frécinaux # # 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 of the License, 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. import gedit import gtk import copy import gettext from gpdefs import * try: gettext.bindtextdomain(GETTEXT_PACKAGE, GP_LOCALEDIR) _ = lambda s: gettext.dgettext(GETTEXT_PACKAGE, s); except: _ = lambda s: s def get_comment_tags(lang): start_tag = lang.get_metadata('line-comment-start') if start_tag: return (start_tag, None) start_tag = lang.get_metadata('block-comment-start') end_tag = lang.get_metadata('block-comment-end') if start_tag and end_tag: return (start_tag, end_tag) return (None, None) def forward_tag(iter, tag): iter.forward_chars(len(tag)) def backward_tag(iter, tag): iter.backward_chars(len(tag)) def get_tag_position_in_line(tag, head_iter, iter): found = False while (not found) and (not iter.ends_line()): s = iter.get_slice(head_iter) if s == tag: found = True else: head_iter.forward_char() iter.forward_char() return found def add_comment_characters(document, start_tag, end_tag, start, end): smark = document.create_mark("start", start, False) imark = document.create_mark("iter", start, False) emark = document.create_mark("end", end, False) number_lines = end.get_line() - start.get_line() + 1 document.begin_user_action() for i in range(0, number_lines): iter = document.get_iter_at_mark(imark) if not iter.ends_line(): document.insert(iter, start_tag, -1) if end_tag is not None: if i != number_lines -1: iter = document.get_iter_at_mark(imark) iter.forward_to_line_end() document.insert(iter, end_tag, -1) else: iter = document.get_iter_at_mark(emark) document.insert(iter, end_tag, -1) iter = document.get_iter_at_mark(imark) iter.forward_line() document.delete_mark(imark) imark = document.create_mark("iter", iter, True) document.end_user_action() document.delete_mark(imark) new_start = document.get_iter_at_mark(smark) new_end = document.get_iter_at_mark(emark) if not new_start.ends_line(): backward_tag(new_start, start_tag) document.select_range(new_start, new_end) document.delete_mark(smark) document.delete_mark(emark) def remove_comment_characters(document, start_tag, end_tag, start, end): smark = document.create_mark("start", start, False) emark = document.create_mark("end", end, False) number_lines = end.get_line() - start.get_line() + 1 iter = start.copy() head_iter = iter.copy() forward_tag(head_iter, start_tag) document.begin_user_action() for i in range(0, number_lines): if get_tag_position_in_line(start_tag, head_iter, iter): dmark = document.create_mark("delete", iter, False) document.delete(iter, head_iter) if end_tag is not None: iter = document.get_iter_at_mark(dmark) head_iter = iter.copy() forward_tag(head_iter, end_tag) if get_tag_position_in_line(end_tag, head_iter, iter): document.delete(iter, head_iter) document.delete_mark(dmark) iter = document.get_iter_at_mark(smark) iter.forward_line() document.delete_mark(smark) head_iter = iter.copy() forward_tag(head_iter, start_tag) smark = document.create_mark("iter", iter, True) document.end_user_action() document.delete_mark(smark) document.delete_mark(emark) def do_comment(document, unindent=False): selection = document.get_selection_bounds() currentPosMark = document.get_insert() deselect = False if selection != (): (start, end) = selection if start.ends_line(): start.forward_char() elif not start.starts_line(): start.set_line_offset(0) if end.starts_line(): end.backward_char() elif not end.ends_line(): end.forward_to_line_end() else: deselect = True start = document.get_iter_at_mark(currentPosMark) start.set_line_offset(0) end = start.copy() end.forward_to_line_end() lang = document.get_language() if lang is None: return (start_tag, end_tag) = get_comment_tags(lang) if not start_tag and not end_tag: return if unindent: # Select the comment or the uncomment method new_code = remove_comment_characters(document, start_tag, end_tag, start, end) else: new_code = add_comment_characters(document, start_tag, end_tag, start, end) if deselect: oldPosIter = document.get_iter_at_mark(currentPosMark) document.select_range(oldPosIter,oldPosIter) document.place_cursor(oldPosIter) ui_str = """ """ class CodeCommentWindowHelper(object): def __init__(self, plugin, window): self._window = window self._plugin = plugin self._insert_menu() def deactivate(self): self._remove_menu() self._action_group = None self._window = None self._plugin = None def _insert_menu(self): manager = self._window.get_ui_manager() self._action_group = gtk.ActionGroup("CodeCommentActions") self._action_group.add_actions([("CodeComment", None, _("Co_mment Code"), "M", _("Comment the selected code"), lambda a, w: do_comment (w.get_active_document())), ('CodeUncomment', None, _('U_ncomment Code'), "M", _("Uncomment the selected code"), lambda a, w: do_comment (w.get_active_document(), True))], self._window) manager.insert_action_group(self._action_group, -1) self._ui_id = manager.add_ui_from_string(ui_str) def _remove_menu(self): manager = self._window.get_ui_manager() manager.remove_ui(self._ui_id) manager.remove_action_group(self._action_group) manager.ensure_update() def update_ui(self): doc = self._window.get_active_document() if doc: lang = doc.get_language() if lang is not None: sensitive = get_comment_tags(lang) != (None, None) self._action_group.set_sensitive(sensitive) return self._action_group.set_sensitive(False) class CodeCommentPlugin(gedit.Plugin): DATA_TAG = "CodeCommentPluginWindowHelper" def __init__(self): gedit.Plugin.__init__(self) def activate(self, window): window.set_data(self.DATA_TAG, CodeCommentWindowHelper(self, window)) def deactivate(self, window): window.get_data(self.DATA_TAG).deactivate() window.set_data(self.DATA_TAG, None) def update_ui(self, window): window.get_data(self.DATA_TAG).update_ui() # ex:ts=4:et: