Seekme
Seekme

Reputation: 174

Copy entire line shortcuts then paste it UNDER cursor

On Sublime Text 3 (but I guess it's the same with ST2), I know that when you copy ( CTRL + C ) when there is nothing selected, the entire line is copied but I need to know how to paste it below my cursor.

It currently paste it above it and it doesn't seem logical to me, is there a way to modify this behaviour ?

Upvotes: 1

Views: 422

Answers (2)

Dan Lowe
Dan Lowe

Reputation: 56637

It's not that it pastes "above" or "below", it's that it is operating on the current line. When you copy without first making a selection, it copies the current line. When you paste that, it also operates on the current line -- it pastes the buffer into that line, and as a side effect, whatever was on that line is bumped out of the way to the next line. It can't be bumped upward instead - the file can only grow or add new lines downward, you can't grow upward beyond line 1.

As to how to modify the behavior, I would suggest trying to make a macro.

http://docs.sublimetext.info/en/latest/extensibility/macros.html

As you pointed out in the comments, a macro works but it leaves you with two different ways to do a paste, one for normal use and the other for this "entire line" behavior. That is unfortunate, though there is another (harder) solution. You could try to write a Sublime plugin to detect how to behave and do what you want in each case. This is a bit beyond my ability to do for you... but in thinking about this, I realized that the Vintage package already has a command for this, because its p and P keys paste before and after the cursor, respectively. I looked inside the Vintage package to find where they did it. Here is their code, though I couldn't explain to you exactly how it works. You would want to try to emulate ViPasteRight.

class ViPrefixableCommand(sublime_plugin.TextCommand):
    # Ensure register and repeat are picked up from g_input_state, and that
    # it'll be recorded on the undo stack
    def run_(self, edit_token, args):
        if not args:
            args = {}

        if g_input_state.register:
            args['register'] = g_input_state.register
            g_input_state.register = None

        if g_input_state.prefix_repeat_digits:
            args['repeat'] = digits_to_number(g_input_state.prefix_repeat_digits)
            g_input_state.prefix_repeat_digits = []

        if 'event' in args:
            del args['event']

        edit = self.view.begin_edit(edit_token, self.name(), args)
        try:
            return self.run(edit, **args)
        finally:
            self.view.end_edit(edit)

class ViPasteRight(ViPrefixableCommand):
    def advance(self, pt):
        if self.view.substr(pt) == '\n' or pt >= self.view.size():
            return pt
        else:
            return pt + 1

    def run(self, edit, register = '"', repeat = 1):
        visual_mode = self.view.has_non_empty_selection_region()
        if not visual_mode:
            transform_selection(self.view, lambda pt: self.advance(pt))
        self.view.run_command('paste_from_register', {'forward': not visual_mode,
                                                      'repeat': repeat,
                                                      'register': register})

class ViPasteLeft(ViPrefixableCommand):
    def run(self, edit, register = '"', repeat = 1):
        self.view.run_command('paste_from_register', {'forward': False,
                                                      'repeat': repeat,
                                                      'register': register})

And here is how they bind them to keys. If you wanted to try to adapt this you probably would not need the context, that is something they need due to Vintage mode's modal nature.

{ "keys": ["P"], "command": "vi_paste_left",
    "context": [{"key": "setting.command_mode"}]
},

{ "keys": ["p"], "command": "vi_paste_right",
    "context": [{"key": "setting.command_mode"}]
},

Here is the docs section about plugins, if you want to try to tackle it that way.

http://docs.sublimetext.info/en/latest/extensibility/plugins.html

Upvotes: 1

Seekme
Seekme

Reputation: 174

Following Dan Lowe's answer, I made this file :
http://pastebin.com/7nPWZCPh
and added this line
{ "keys": ["ctrl+shift+v"], "command": "run_macro_file", "args": {"file": "res://Packages/User/paste_no_line.sublime-macro"}},
to my user's keybindings.
Works as intended but I have two differente "paste command" now.

Upvotes: 1

Related Questions