Last active
May 12, 2016 17:55
-
-
Save davidkuster/634f286d24d7654b7232934ea3911262 to your computer and use it in GitHub Desktop.
Start of a Sublime Text 2 plugin to use Sublime instead of a browser-based code editor as the front end for a Groovy REPL
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import sublime | |
import sublime_plugin | |
import threading | |
import urllib | |
import urllib2 | |
# Sublime plugin to use Groovy REPL functionality as offered by a Spring Boot | |
# app with the necessary server-side support. | |
# | |
# Plugin functions: | |
# ----------------- | |
# Command+Enter | |
# - Sends contents of current buffer to the server to be run | |
# - The response from the server is placed into a buffer with an internal ID | |
# tied to the REPL plugin. If a buffer with this ID does not exist it will be | |
# created and opened. Once open it can be moved to a different pane and all | |
# subsequent executions will target the results into this pane. | |
# - A comment of some sort at the top of the file will contain the URL to send | |
# the code buffer too. For instance, something like: | |
# // repl_url: http://localhost:8001/repl | |
# This will allow different ports and endpoints to be used. By convention, a | |
# URL parameter of "?script=<URL escaped buffer contents>" will be appended to | |
# the URL in the comment. | |
# | |
# Options | |
# - Determine whether the output pane is cleared on every run or if results are | |
# appended to the existing output. Default is to clear on every run. | |
# - Set the server base URL so it does not need to be specified via a comment in | |
# the code buffer. | |
# | |
# Development note: | |
# - open Sublime console: Ctrl+` | |
# - log commands in console: sublime.log_commands(True) | |
# The parent command for the plugin | |
class RunGroovyRepl(sublime_plugin.TextCommand): | |
def run(self, edit): | |
code = self.view.substr(sublime.Region(0, self.view.size())) | |
#print "sending code to server:", code | |
thread = SendGroovyReplCodeToServer(code, 5) | |
thread.start() | |
self.handle_thread([thread]) | |
def handle_thread(self, threads): | |
next_threads = [] | |
for t in threads: | |
if t.is_alive(): | |
next_threads.append(t) | |
continue | |
if t.result == False: | |
continue | |
# thread has completed | |
self.handle_result(t.result) | |
threads = next_threads | |
if len(threads): | |
sublime.status_message('GroovyREPL running...') | |
sublime.set_timeout(lambda: self.handle_thread(threads), 100) | |
return | |
sublime.status_message('GroovyREPL completed') | |
# display the results in a separate buffer | |
def handle_result(self, result): | |
if not hasattr(self, 'output_view'): | |
#self.output_view = self.view.window().get_output_panel("groovy_repl_results") | |
self.output_view = self.view.window().new_file() | |
self.output_view.set_name("groovy_repl_results") | |
self.output_view.set_scratch(True) | |
data = json.loads(result) | |
self.index = 0 | |
self.output_view.set_read_only(False) | |
edit = self.output_view.begin_edit() | |
self.output_view.erase(edit, sublime.Region(0, self.output_view.size())) | |
self.print_result(edit, "Execution completed in " + data['time'] + "ms") | |
if data['output']: | |
self.print_result(edit, "\nOutput") | |
self.print_result(edit, "------") | |
self.print_result(edit, data['output']) | |
self.print_result(edit, "Result") | |
self.print_result(edit, "------") | |
self.print_result(edit, data['result']) | |
self.output_view.end_edit(edit) | |
# prints results to the output_view | |
def print_result(self, edit, text): | |
self.output_view.insert(edit, self.index, '\n' + text) | |
self.index += len(text) + 1 | |
# Makes the API call to the server | |
class SendGroovyReplCodeToServer(threading.Thread): | |
def __init__(self, string, timeout): | |
self.original = string | |
self.timeout = timeout | |
self.result = None | |
threading.Thread.__init__(self) | |
def run(self): | |
try: | |
data = urllib.urlencode({'script': self.original}) | |
url = 'http://localhost:8001/repl?' + data | |
request = urllib2.Request(url) | |
#print "request:", url | |
http_file = urllib2.urlopen(request, timeout=self.timeout) | |
self.result = http_file.read() | |
return | |
except (urllib2.HTTPError) as (e): | |
err = '%s: HTTP error %s contacting API' % (__name__, str(e.code)) | |
except (urllib2.URLError) as (e): | |
err = '%s: URL error %s contacting API' % (__name__, str(e.reason)) | |
sublime.error_message(err) | |
self.result = False |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment