Question

I am using Sublime Text 3 and running OSX Mavericks. I am using the Sublime REPL package and I have adjusted the settings for that package such that I have "show_transferred_text" : true

When a Python REPL window is opened, I have the nice option to send a chunk of code from the editor to it using Ctrl + , , s . But, doing so doesn't display any of the output of my commands, unless I include a print command. E.g. If I write the following

x = 2.5

type(x)

and use the Ctrl +, , s to send it to be evaluated, then I do get a display of these commands, but I don't get a display of the output from type(x) as I would if I copy/pasted the commands into the Python interpreter in the Mac Terminal.

Is there any way to get this functionality within Sublime Text?

Was it helpful?

Solution

[UPDATE]

The code below is now deprecated. For the newest, better working version, please visit the gist for this plugin at https://gist.github.com/dantonnoriega/46c40275a93bab74cff6.

Feel free to fork and star. I will add any changes to the gist as the code evolves. However, to stay the most up-to-date, please following the following repo: https://github.com/dantonnoriega/sublime_text_plugins/blob/master/python_blocks_for_repl.py

***************

I wanted the same functionality. What I came up with works and is a hodgepodge of the following posts:

https://stackoverflow.com/a/14091739/3987905

Is it possible to chain key binding commands in sublime text 2?

How to pass a line to the console in sublime text 2 editor

Creating the Plugin

The following plugin requires that you open repl in the same window as your code but as a separate group. I learned how to do this using the 1st link above. In order to send the text you want and then execute the text, I used the idea from the 2nd link above and wrote the following plugin (Tools -> New Plugin...)

class ReplViewAndExecute(sublime_plugin.TextCommand):
    def run(self, edit):
        v = self.view
        ex_id = v.scope_name(0).split(" ")[0].split(".", 1)[1]
        lines = v.lines(self.view.sel()[0]) # get the region, ordered
        last_point = v.line(self.view.sel()[0]).b # get last point (must use v.line)
        last_line = v.line(last_point) # get region of last line

        for line in lines:
            self.view.sel().clear() # clear selection
            self.view.sel().add(line) # add the first region/line
            text = v.substr(line)
            print('%s' % text) # prints in console (ctrl+`)

            if not line.empty() and text[0] != '#': # ignore empty lines or comments
                v.window().run_command('focus_group', {"group": 1}) # focus REPL
                v.window().active_view().run_command("insert",
                    {"characters": text})
                v.window().run_command('repl_enter')

        # if the last line was empty, hit return
        # else, move the cursor down. check if empty, hit return once more
        if last_line.empty():
            self.view.sel().clear()
            self.view.sel().add(last_line)
            v.window().run_command('focus_group', {"group": 1}) # focus REPL
            v.window().run_command('repl_enter')
            v.window().run_command('focus_group', {"group": 0})
            v.window().run_command('move', {
                "by": "lines",
                "forward": True,
                "extend": False
            })
        else:
            v.window().run_command('focus_group', {"group": 0})
            v.window().run_command('move', {
                "by": "lines",
                "forward": True,
                "extend": False
            })
            if self.empty_space():
                v.window().run_command('focus_group', {"group": 1}) # focus REPL
                v.window().run_command('repl_enter')

        # move through empty space
        while self.empty_space() and self.eof():
            v.window().run_command('focus_group', {"group": 0})
            v.window().run_command('move', {
                "by": "lines",
                "forward": True,
                "extend": False
            })
    def eof(self):
        v = self.view
        s = v.sel()
        return True if v.line(s[0]).b < v.size() else False

    def empty_space(self):
        v = self.view
        s = v.sel()
        return True if v.line(s[0]).empty() else False

The code above sends the selected line(s) to REPL, focuses the group where REPL is contained, executes REPL (i.e. hits 'enter') then focuses back to the code window.

The plugin now moves the cursor to the next line automatically so you can evaluate lines quickly. Also, if the next line happens to be empty, the plugin keeps hitting 'enter' for you automatically until it encounters a non-empty line. This, for me, was key, since if I selected a function block in python, I would still have to switch over to REPL and hit enter for the function to complete. The while loop part fixes that.

Using the Plugin

To run the following plugin, I put the following in my user key bindings (which I learned from the 3rd link above)...

    //REPL send and evaluate
    { "keys": ["super+enter"], "command": "repl_view_and_execute"}

And that should work!

Summary

Remember, you need to

  1. Put sublimeREPL in the same window but in a separate group (follow the first link to do this quickly with the pydev plugin).
  2. Create the 'repl_view_and_execute' plugin then bind it.

If anyone knows how to make a more elegant version that can switch between the active window and wherever the REPL view is contained (like another window), I welcome the advice. I worked through sublimerepl.py but could not figure out how to use all the active_window() etc. commands.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top