How to get a "duplicate line" hotkey in gedit?

The plugin mentioned in the comments and the other answer has been recently updated and after install you should be able to use Ctrl+Shift+D to duplicate either a line or a selection.

I've tested it in gedit 3.18.3 on Ubuntu 16.04 but it should work in any version >=3.14.0 even though that's a bit questionable because the gedit devs are not shy to introduce breaking changes in minor versions (or they follow something else than semantic versioning) and there seems to be no up-to-date documentation for plugin development.


Do you still look for an answer? I think I have the right one, though I'm not sure, because I'm not familiar with python.
1. You should edit duplicateline.py file from plugin for gedit3 this way:


import gettext
from gi.repository import GObject, Gtk, Gio, Gedit
ACCELERATOR = ['<Alt>d']

#class DuplicateLineWindowActivatable(GObject.Object, Gedit.WindowActivatable):
class DuplicateLineAppActivatable(GObject.Object, Gedit.AppActivatable):
    __gtype_name__ = "DuplicateLineWindowActivatable"

    app = GObject.Property(type=Gedit.App)

    def __init__(self):
        GObject.Object.__init__(self)

    def do_activate(self):
        #self._insert_menu()
        self.app.set_accels_for_action("win.duplicate", ACCELERATOR)
        self.menu_ext = self.extend_menu("tools-section")
        item = Gio.MenuItem.new(_("Duplicate Line"), "win.duplicate")
        self.menu_ext.prepend_menu_item(item)

    def do_deactivate(self):
        #self._remove_menu()
        self.app.set_accels_for_action("win.duplicate", [])
        self.menu_ext = None

        #self._action_group = None

    #def _insert_menu(self):
        #manager = self.window.get_ui_manager()

        # Add our menu action and set ctrl+shift+D to activate.
        #self._action_group = Gtk.ActionGroup("DuplicateLinePluginActions")
        #self._action_group.add_actions([(
            #"DuplicateLine",
            #None,
            #_("Duplicate Line"),
            #"d",
            #_("Duplicate current line, current selection or selected lines"),
            #self.on_duplicate_line_activate
        #)])

        #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 do_update_state(self):
        #self._action_group.set_sensitive(self.window.get_active_document() != None)
        pass
class DuplicateLineWindowActivatable(GObject.Object, Gedit.WindowActivatable):
    window = GObject.property(type=Gedit.Window)

    def __init__(self):
        GObject.Object.__init__(self)
        self.settings = Gio.Settings.new("org.gnome.gedit.preferences.editor")

    def do_activate(self):
        action = Gio.SimpleAction(name="duplicate")
        action.connect('activate', self.on_duplicate_line_activate)
        self.window.add_action(action)

    def on_duplicate_line_activate(self, action, user_data=None):
        doc = self.window.get_active_document()
        if not doc:
            return

        if doc.get_has_selection():
            # User has text selected, get bounds.
            s, e = doc.get_selection_bounds()
            l1 = s.get_line()
            l2 = e.get_line()

            if l1 != l2:
                # Multi-lines selected. Grab the text, insert.
                s.set_line_offset(0)
                e.set_line_offset(e.get_chars_in_line())

                text = doc.get_text(s, e, False)
                if text[-1:] != '\n':
                    # Text doesn't have a new line at the end. Add one for the beginning of the next.
                    text = "\n" + text

                doc.insert(e, text)
            else:
                # Same line selected. Grab the text, insert on same line after selection.
                text = doc.get_text(s, e, False)
                doc.move_mark_by_name("selection_bound", s)
                doc.insert(e, text)
        else:
            # No selection made. Grab the current line the cursor is on, insert on new line.
            s = doc.get_iter_at_mark(doc.get_insert())
            e = doc.get_iter_at_mark(doc.get_insert())
            s.set_line_offset(0)

            if not e.ends_line():
                e.forward_to_line_end()

            text = "\n" + doc.get_text(s, e, False)

            doc.insert(e, text)



2. Alt+D duplicates a line. You may change the hot key - edit the 3d line "ACCELERATOR = ['<Alt>d']" as you see fit.
3. At least, it works for gedit v. 3.14.3.