# -*- coding: utf-8 -*-
# Join lines plugin
# This file is part of gedit
#
# Copyright (C) 2006-2007 Steve Frécinaux, André Homeyer
#
# 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., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301, USA.
from gi.repository import GObject, Gio, Gtk, Gedit
from gpdefs import *
try:
import gettext
gettext.bindtextdomain('gedit-plugins')
gettext.textdomain('gedit-plugins')
_ = gettext.gettext
except:
_ = lambda s: s
class JoinLinesAppActivatable(GObject.Object, Gedit.AppActivatable):
app = GObject.Property(type=Gedit.App)
def __init__(self):
GObject.Object.__init__(self)
def do_activate(self):
self.app.add_accelerator("<Primary>J", "win.joinlines", None)
self.app.add_accelerator("<Primary><Shift>J", "win.splitlines", None)
def do_deactivate(self):
self.app.remove_accelerator("win.joinlines", None)
self.app.remove_accelerator("win.splitlines", None)
class JoinLinesWindowActivatable(GObject.Object, Gedit.WindowActivatable):
window = GObject.Property(type=Gedit.Window)
def __init__(self):
GObject.Object.__init__(self)
def do_activate(self):
action = Gio.SimpleAction(name="joinlines")
action.connect('activate', lambda a, p: self.join_lines())
self.window.add_action(action)
action = Gio.SimpleAction(name="splitlines")
action.connect('activate', lambda a, p: self.split_lines())
self.window.add_action(action)
def do_deactivate(self):
self.window.remove_action("joinlines")
self.window.remove_action("splitlines")
def do_update_state(self):
view = self.window.get_active_view()
enable = view is not None and view.get_editable()
self.window.lookup_action("joinlines").set_enabled(enable)
self.window.lookup_action("splitlines").set_enabled(enable)
def join_lines(self):
view = self.window.get_active_view()
if view and hasattr(view, "join_lines_view_activatable"):
view.join_lines_view_activatable.join_lines()
def split_lines(self):
view = self.window.get_active_view()
if view and hasattr(view, "join_lines_view_activatable"):
view.join_lines_view_activatable.split_lines()
class JoinLinesViewActivatable(GObject.Object, Gedit.ViewActivatable):
view = GObject.Property(type=Gedit.View)
def __init__(self):
self.popup_handler_id = 0
GObject.Object.__init__(self)
def do_activate(self):
self.view.join_lines_view_activatable = self
self.popup_handler_id = self.view.connect('populate-popup', self.populate_popup)
def do_deactivate(self):
if self.popup_handler_id != 0:
self.view.disconnect(self.popup_handler_id)
self.popup_handler_id = 0
delattr(self.view, "join_lines_view_activatable")
def populate_popup(self, view, popup):
if not isinstance(popup, Gtk.MenuShell):
return
item = Gtk.SeparatorMenuItem()
item.show()
popup.append(item)
item = Gtk.MenuItem.new_with_mnemonic(_("_Join Lines"))
item.set_sensitive(self.view.get_editable())
item.show()
item.connect('activate', lambda i: self.join_lines())
popup.append(item)
item = Gtk.MenuItem.new_with_mnemonic(_('_Split Lines'))
item.set_sensitive(self.view.get_editable())
item.show()
item.connect('activate', lambda i: self.split_lines())
popup.append(item)
def join_lines(self):
doc = self.view.get_buffer()
if doc is None:
return
# If there is a selection use it, otherwise join the
# next line
try:
start, end = doc.get_selection_bounds()
except ValueError:
start = doc.get_iter_at_mark(doc.get_insert())
end = start.copy()
end.forward_line()
doc.join_lines(start, end)
def split_lines(self):
doc = self.view.get_buffer()
if doc is None:
return
width = self.view.get_right_margin_position()
tabwidth = self.view.get_tab_width()
doc.begin_user_action()
try:
# get selection bounds
start, end = doc.get_selection_bounds()
# measure indent until selection start
indent_iter = start.copy()
indent_iter.set_line_offset(0)
indent = ''
while indent_iter.get_offset() != start.get_offset():
if indent_iter.get_char() == '\t':
indent = indent + '\t'
else:
indent = indent + ' '
indent_iter.forward_char()
except ValueError:
# select from start to line end
start = doc.get_iter_at_mark(doc.get_insert())
start.set_line_offset(0)
end = start.copy()
if not end.ends_line():
end.forward_to_line_end()
# measure indent of line
indent_iter = start.copy()
indent = ''
while indent_iter.get_char() in (' ', '\t'):
indent = indent + indent_iter.get_char()
indent_iter.forward_char()
end_mark = doc.create_mark(None, end)
# ignore first word
previous_word_end = start.copy()
forward_to_word_start(previous_word_end)
forward_to_word_end(previous_word_end)
while 1:
current_word_start = previous_word_end.copy()
forward_to_word_start(current_word_start)
current_word_end = current_word_start.copy()
forward_to_word_end(current_word_end)
if (not current_word_end.is_end()) and \
doc.get_iter_at_mark(end_mark).compare(current_word_end) >= 0:
word_length = current_word_end.get_offset() - \
current_word_start.get_offset()
doc.delete(previous_word_end, current_word_start)
line_offset = self.view.get_visual_column(current_word_start)
if line_offset + word_length > width - 1:
doc.insert(current_word_start, '\n' + indent)
else:
doc.insert(current_word_start, ' ')
previous_word_end = current_word_start.copy()
previous_word_end.forward_chars(word_length)
else:
break
doc.delete_mark(end_mark)
doc.end_user_action()
def forward_to_word_start(text_iter):
char = text_iter.get_char()
while not text_iter.is_end() and char in (' ', '\t', '\n', '\r'):
text_iter.forward_char()
char = text_iter.get_char()
def forward_to_word_end(text_iter):
char = text_iter.get_char()
while not text_iter.is_end() and not (char in (' ', '\t', '\n', '\r')):
text_iter.forward_char()
char = text_iter.get_char()
# ex:ts=4:et: