Skip to content

Instantly share code, notes, and snippets.

@davidkuster
Last active May 12, 2016 17:55
Show Gist options
  • Save davidkuster/634f286d24d7654b7232934ea3911262 to your computer and use it in GitHub Desktop.
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
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