1from gi.repository import GObject, Gtk, Xed
2
3import gettext
4gettext.install("xed")
5
6MENU_PATH = "/MenuBar/ViewMenu/ViewOps_1"
7
8class JoinLinesPlugin(GObject.Object, Xed.WindowActivatable):
9    __gtype_name__ = "JoinLinesPlugin"
10
11    window = GObject.property(type=Xed.Window)
12
13    def __init__(self):
14        GObject.Object.__init__(self)
15
16    def do_activate(self):
17        self._views = {}
18
19        self._insert_menu()
20
21    def _insert_menu(self):
22        manager = self.window.get_ui_manager()
23
24        self._action_group = Gtk.ActionGroup(name="XedJoinLinesPluginActions")
25        self._action_group.add_actions(
26            [("JoinLinesAction", None, _("_Join Lines"), "<Ctrl>J",
27              _("Join the selected lines"),
28              lambda w: self.join_lines(w))])
29
30        manager.insert_action_group(self._action_group)
31
32        self._ui_id = manager.new_merge_id()
33
34        manager.add_ui(self._ui_id,
35                       MENU_PATH,
36                       "JoinLinesAction",
37                       "JoinLinesAction",
38                       Gtk.UIManagerItemType.MENUITEM,
39                       False)
40
41    def do_update_state(self):
42        self._action_group.set_sensitive(self.window.get_active_document() != None)
43
44    def do_deactivate(self):
45        self._remove_menu()
46
47
48    def _remove_menu(self):
49        manager = self.window.get_ui_manager()
50        manager.remove_ui(self._ui_id)
51        manager.remove_action_group(self._action_group)
52        manager.ensure_update()
53
54    def join_lines(self, w):
55        doc = self.window.get_active_document()
56        if doc is None:
57            return
58
59        doc.begin_user_action()
60
61        # If there is a selection use it, otherwise join the
62        # next line
63        try:
64            start, end = doc.get_selection_bounds()
65        except ValueError:
66            start = doc.get_iter_at_mark(doc.get_insert())
67            end = start.copy()
68            end.forward_line()
69
70        end_mark = doc.create_mark(None, end)
71
72        if not start.ends_line():
73            start.forward_to_line_end()
74
75        # Include trailing spaces in the chunk to be removed
76        while start.backward_char() and start.get_char() in ('\t', ' '):
77            pass
78        start.forward_char()
79
80        while doc.get_iter_at_mark(end_mark).compare(start) == 1:
81            end = start.copy()
82            while end.get_char() in ('\r', '\n', ' ', '\t'):
83                end.forward_char()
84            doc.delete(start, end)
85
86            doc.insert(start, ' ')
87            start.forward_to_line_end()
88
89        doc.delete_mark(end_mark)
90        doc.end_user_action()
91
92