Reorganized code, added Wallaby hostnames, added sync, added compile view, improved window handling
This commit is contained in:
parent
2ef7a5c1c1
commit
23c937b356
1 changed files with 105 additions and 67 deletions
|
@ -19,34 +19,30 @@ import sublime_plugin
|
||||||
import socket
|
import socket
|
||||||
from ESock import ESock
|
from ESock import ESock
|
||||||
from Utils import capture_trace
|
from Utils import capture_trace
|
||||||
|
from Sync import SyncClient
|
||||||
import Routing
|
import Routing
|
||||||
from SublimeMenu import *
|
from SublimeMenu import *
|
||||||
import Logging
|
import Logging
|
||||||
|
|
||||||
import webbrowser
|
import webbrowser
|
||||||
|
|
||||||
|
CHANNEL = "s"
|
||||||
|
|
||||||
def plugin_unloaded():
|
def plugin_unloaded():
|
||||||
observer.stop()
|
for window in windows:
|
||||||
try:
|
if hasattr(window, "fl0w"):
|
||||||
for window in windows:
|
window.fl0w.invoke_disconnect()
|
||||||
if hasattr(window, "fl0w"):
|
|
||||||
window.fl0w.invoke_disconnect()
|
|
||||||
except:
|
|
||||||
print("Error while unloading fl0w for %s" % window.folders())
|
|
||||||
print("Observer stopped!")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def sock_handler(sock, routes, handler):
|
def sock_handler(sock, routes, handler):
|
||||||
sock.send("st", "set_type")
|
|
||||||
while 1:
|
while 1:
|
||||||
try:
|
try:
|
||||||
data = sock.recv()
|
data = sock.recv()
|
||||||
if data[1] in routes:
|
if data[1] in routes:
|
||||||
routes[data[1]].run(data[0], handler)
|
routes[data[1]].run(data[0], handler)
|
||||||
except (OSError, socket.error, Exception) as e:
|
except (OSError, socket.error, Exception) as e:
|
||||||
if e is Exception:
|
if str(e) != "[Errno 9] Bad file descriptor":
|
||||||
Logging.info("Exception occured in network thread.")
|
|
||||||
capture_trace()
|
capture_trace()
|
||||||
handler.invoke_disconnect()
|
handler.invoke_disconnect()
|
||||||
break
|
break
|
||||||
|
@ -60,7 +56,8 @@ class ReloadHandler(FileSystemEventHandler):
|
||||||
print("Created: %s" % event)
|
print("Created: %s" % event)
|
||||||
|
|
||||||
def on_deleted(self, event):
|
def on_deleted(self, event):
|
||||||
print("Deleted: %s" % event)
|
print("Deleted: %s" % event)
|
||||||
|
|
||||||
|
|
||||||
class Fl0w:
|
class Fl0w:
|
||||||
def __init__(self, window):
|
def __init__(self, window):
|
||||||
|
@ -79,23 +76,95 @@ class Fl0w:
|
||||||
self.main_menu.add(Entry("Disconnect", "Disconnect from server", action=self.invoke_disconnect))
|
self.main_menu.add(Entry("Disconnect", "Disconnect from server", action=self.invoke_disconnect))
|
||||||
|
|
||||||
|
|
||||||
|
def invoke_about(self):
|
||||||
|
if sublime.ok_cancel_dialog("fl0w by @robot0nfire", "robot0nfire.com"):
|
||||||
|
webbrowser.open("http://robot0nfire.com")
|
||||||
|
|
||||||
|
|
||||||
|
def invoke_info(self):
|
||||||
|
self.sock.send("", "info")
|
||||||
|
|
||||||
|
|
||||||
|
class Info(Routing.ClientRoute):
|
||||||
|
def run(self, data, handler):
|
||||||
|
sublime.message_dialog(data)
|
||||||
|
handler.main_menu.invoke(handler.window)
|
||||||
|
|
||||||
|
|
||||||
|
class GetInfo(Routing.ClientRoute):
|
||||||
|
def run(self, data, handler):
|
||||||
|
if data == "":
|
||||||
|
handler.sock.send({"type" : CHANNEL}, "get_info")
|
||||||
|
|
||||||
|
|
||||||
class ErrorReport(Routing.ClientRoute):
|
class ErrorReport(Routing.ClientRoute):
|
||||||
def run(self, data, handler):
|
def run(self, data, handler):
|
||||||
sublime.error_message(data)
|
sublime.error_message(data)
|
||||||
|
|
||||||
|
|
||||||
|
class Compile(Routing.ClientRoute):
|
||||||
|
def run(self, data, handler):
|
||||||
|
status = ""
|
||||||
|
if data["failed"]:
|
||||||
|
status = "Compile failed (%s)." % data["relpath"]
|
||||||
|
else:
|
||||||
|
status = "Compile completed successfully. (%s)." % data["relpath"]
|
||||||
|
view = handler.window.create_output_panel('compile_panel')
|
||||||
|
view.set_syntax_file("Packages/fl0w/CompileHighlight.sublime-syntax")
|
||||||
|
view.settings().set("draw_white_space", "none")
|
||||||
|
view.settings().set("draw_indent_guides", False)
|
||||||
|
view.settings().set("gutter", False)
|
||||||
|
view.settings().set("line_numbers", False)
|
||||||
|
view.set_read_only(False)
|
||||||
|
view.run_command("append", {"characters": data["returned"] + status})
|
||||||
|
view.set_read_only(True)
|
||||||
|
handler.window.run_command("show_panel", {"panel": "output.compile_panel"})
|
||||||
|
|
||||||
|
|
||||||
|
def connect(self, connect_details):
|
||||||
|
connect_details_raw = connect_details
|
||||||
|
connect_details = connect_details.split(":")
|
||||||
|
if len(connect_details) == 2:
|
||||||
|
try:
|
||||||
|
# Establish connection to the server
|
||||||
|
self.sock = ESock(socket.create_connection((connect_details[0], int(connect_details[1]))), disconnect_callback=self.invoke_disconnect, debug=False)
|
||||||
|
sublime.status_message("Connected to %s:%s." % (connect_details[0], connect_details[1]))
|
||||||
|
self.connected = True
|
||||||
|
# Initialize all routes
|
||||||
|
error_report = Fl0w.ErrorReport()
|
||||||
|
info = Fl0w.Info()
|
||||||
|
wallaby_control = Fl0w.WallabyControl()
|
||||||
|
get_info = Fl0w.GetInfo()
|
||||||
|
self.s_sync = SyncClient(self.sock, self.folder, "s_sync")
|
||||||
|
compile = Fl0w.Compile()
|
||||||
|
_thread.start_new_thread(sock_handler, (self.sock, {"error_report": error_report,
|
||||||
|
"info" : info, "wallaby_control" : wallaby_control, "get_info" : get_info,
|
||||||
|
"s_sync" : self.s_sync, "compile" : compile}, self))
|
||||||
|
self.s_sync.start()
|
||||||
|
# Saving last server address
|
||||||
|
sublime.load_settings("fl0w.sublime-setting").set("server_address", connect_details_raw)
|
||||||
|
sublime.save_settings("fl0w.sublime-setting")
|
||||||
|
except OSError as e:
|
||||||
|
sublime.error_message("Error during connection creation:\n %s" % str(e))
|
||||||
|
else:
|
||||||
|
sublime.error_message("Invalid input.")
|
||||||
|
|
||||||
|
|
||||||
# Input invokers
|
# Input invokers
|
||||||
def invoke_connect(self):
|
def invoke_connect(self):
|
||||||
address = sublime.load_settings("fl0w.sublime-setting").get("server_address")
|
address = sublime.load_settings("fl0w.sublime-setting").get("server_address")
|
||||||
address = "" if type(address) is not str else address
|
address = "" if type(address) is not str else address
|
||||||
Input("Address:Port", initial_text=address, on_done=self.connect).invoke(self.window)
|
Input("Address:Port", initial_text=address, on_done=self.connect).invoke(self.window)
|
||||||
|
|
||||||
def invoke_about(self):
|
|
||||||
if sublime.ok_cancel_dialog("fl0w by @robot0nfire", "robot0nfire.com"):
|
def invoke_disconnect(self):
|
||||||
webbrowser.open("http://robot0nfire.com")
|
if self.connected:
|
||||||
|
sublime.message_dialog("Connection closed ('%s')" % ", ".join(self.folder))
|
||||||
|
if hasattr(self, "s_sync"):
|
||||||
|
self.s_sync.observer.stop()
|
||||||
|
self.connected = False
|
||||||
|
self.sock.close()
|
||||||
|
|
||||||
|
|
||||||
def invoke_wallaby_control(self):
|
def invoke_wallaby_control(self):
|
||||||
self.sock.send("list", "wallaby_control")
|
self.sock.send("list", "wallaby_control")
|
||||||
|
@ -103,21 +172,25 @@ class Fl0w:
|
||||||
|
|
||||||
class WallabyControl(Routing.ClientRoute):
|
class WallabyControl(Routing.ClientRoute):
|
||||||
def run(self, data, handler):
|
def run(self, data, handler):
|
||||||
wallaby_menu = Menu(subtitles=False)
|
wallaby_menu = Menu()
|
||||||
entry_count = 0
|
entry_count = 0
|
||||||
for wallaby in data:
|
for wallaby in data:
|
||||||
wallaby_menu.add(Entry(wallaby, action=handler.wallaby_control_submenu, kwargs={"wallaby" : wallaby}))
|
wallaby_menu.add(Entry(wallaby, str(data[wallaby]), action=handler.wallaby_control_submenu, kwargs={"wallaby" : wallaby}))
|
||||||
entry_count += 1
|
entry_count += 1
|
||||||
if entry_count != 0:
|
if entry_count != 0:
|
||||||
wallaby_menu.invoke(handler.window, back=handler.main_menu)
|
wallaby_menu.invoke(handler.window, back=handler.main_menu)
|
||||||
else:
|
else:
|
||||||
sublime.error_message("No Wallabies connected.")
|
sublime.error_message("No Wallaby Controllers connected.")
|
||||||
|
|
||||||
|
|
||||||
def wallaby_control_submenu(self, wallaby):
|
def wallaby_control_submenu(self, wallaby):
|
||||||
menu = Menu(subtitles=False)
|
menu = Menu(subtitles=False)
|
||||||
for command in ("Stop", "Restart", "Shutdown", "Reboot", "Disconnect"):
|
for action in ("Run", "Stop"):
|
||||||
menu.add(Entry(command, action=self.sock.send, kwargs={"data" : {wallaby : command.lower()}, "route" : "wallaby_control"}))
|
menu.add(Entry(action, action=self.sock.send, kwargs={"data" : {wallaby : action.lower()}, "route" : "wallaby_control"}))
|
||||||
|
for action in ("Restart", "Shutdown", "Reboot", "Disconnect"):
|
||||||
|
menu.add(Entry(action, action=self.sock.send, kwargs={"data" : {wallaby : action.lower()}, "route" : "wallaby_control"}))
|
||||||
|
|
||||||
|
|
||||||
menu.invoke(self.window)
|
menu.invoke(self.window)
|
||||||
|
|
||||||
|
|
||||||
|
@ -133,48 +206,8 @@ class Fl0w:
|
||||||
self.sock.debug = debug
|
self.sock.debug = debug
|
||||||
|
|
||||||
|
|
||||||
def invoke_info(self):
|
|
||||||
self.sock.send("", "info")
|
|
||||||
|
|
||||||
class Info(Routing.ClientRoute):
|
|
||||||
def run(self, data, handler):
|
|
||||||
sublime.message_dialog(data)
|
|
||||||
handler.main_menu.invoke(handler.window)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def invoke_disconnect(self):
|
|
||||||
if self.connected:
|
|
||||||
sublime.message_dialog("Connection closed ('%s')" % ", ".join(self.window.folders()))
|
|
||||||
self.connected = False
|
|
||||||
self.sock.close()
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def connect(self, connect_details):
|
|
||||||
connect_details_raw = connect_details
|
|
||||||
connect_details = connect_details.split(":")
|
|
||||||
if len(connect_details) == 2:
|
|
||||||
try:
|
|
||||||
# Establish connection to the server
|
|
||||||
self.sock = ESock(socket.create_connection((connect_details[0], int(connect_details[1]))), disconnect_callback=self.invoke_disconnect, debug=True)
|
|
||||||
sublime.status_message("Connected to %s:%s." % (connect_details[0], connect_details[1]))
|
|
||||||
self.connected = True
|
|
||||||
_thread.start_new_thread(sock_handler, (self.sock, {"error_report": Fl0w.ErrorReport(),
|
|
||||||
"info" : Fl0w.Info(), "wallaby_control" : Fl0w.WallabyControl()}, self))
|
|
||||||
# Saving last server address
|
|
||||||
sublime.load_settings("fl0w.sublime-setting").set("server_address", connect_details_raw)
|
|
||||||
sublime.save_settings("fl0w.sublime-setting")
|
|
||||||
self.main_menu.invoke(self.window)
|
|
||||||
except OSError as e:
|
|
||||||
sublime.error_message("Error during connection creation:\n %s" % str(e))
|
|
||||||
else:
|
|
||||||
sublime.error_message("Invalid input.")
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Fl0wCommand(sublime_plugin.WindowCommand):
|
class Fl0wCommand(sublime_plugin.WindowCommand):
|
||||||
def run(self, menu=None, action=None):
|
def run(self):
|
||||||
valid_window_setup = True
|
valid_window_setup = True
|
||||||
folder_count = len(self.window.folders())
|
folder_count = len(self.window.folders())
|
||||||
if folder_count > 1:
|
if folder_count > 1:
|
||||||
|
@ -188,7 +221,7 @@ class Fl0wCommand(sublime_plugin.WindowCommand):
|
||||||
folder = self.window.folders()[0]
|
folder = self.window.folders()[0]
|
||||||
files = os.listdir(folder)
|
files = os.listdir(folder)
|
||||||
if not ".no-fl0w" in files:
|
if not ".no-fl0w" in files:
|
||||||
if not ".flow" in files:
|
if not ".fl0w" in files:
|
||||||
if sublime.ok_cancel_dialog("""We've detected that this is your first time using fl0w in your current directory.
|
if sublime.ok_cancel_dialog("""We've detected that this is your first time using fl0w in your current directory.
|
||||||
We don't want to be responsible for any lost work so please backup your files before proceding.
|
We don't want to be responsible for any lost work so please backup your files before proceding.
|
||||||
(An empty project directory is recommended but not necessary.)""", "Yes"):
|
(An empty project directory is recommended but not necessary.)""", "Yes"):
|
||||||
|
@ -200,7 +233,8 @@ class Fl0wCommand(sublime_plugin.WindowCommand):
|
||||||
sublime.error_message("fl0w can only be run once you've allowed it to operate in your current directory.")
|
sublime.error_message("fl0w can only be run once you've allowed it to operate in your current directory.")
|
||||||
else:
|
else:
|
||||||
self.window.fl0w = Fl0w(self.window)
|
self.window.fl0w = Fl0w(self.window)
|
||||||
windows.append(self.window)
|
windows.append(self.window)
|
||||||
|
self.window.fl0w.start_menu.invoke(self.window)
|
||||||
else:
|
else:
|
||||||
sublime.error_message("fl0w can't be opened in your current directory (.no-fl0w file exists)")
|
sublime.error_message("fl0w can't be opened in your current directory (.no-fl0w file exists)")
|
||||||
else:
|
else:
|
||||||
|
@ -210,11 +244,15 @@ class Fl0wCommand(sublime_plugin.WindowCommand):
|
||||||
self.window.fl0w.main_menu.invoke(self.window)
|
self.window.fl0w.main_menu.invoke(self.window)
|
||||||
else:
|
else:
|
||||||
if hasattr(self.window, "fl0w"):
|
if hasattr(self.window, "fl0w"):
|
||||||
|
sublime.error_message("Window setup was invalidated (Don't close or open any additional folders in a fl0w window)")
|
||||||
if self.window.fl0w.connected:
|
if self.window.fl0w.connected:
|
||||||
self.window.fl0w.invoke_disconnect()
|
self.window.fl0w.invoke_disconnect()
|
||||||
|
|
||||||
|
def description(self):
|
||||||
|
print("description accessed")
|
||||||
|
if hasattr(self.windows, "fl0w"):
|
||||||
|
return "Connected."
|
||||||
|
return None
|
||||||
|
|
||||||
windows = []
|
|
||||||
observer = Observer()
|
windows = []
|
||||||
observer.schedule(ReloadHandler(), path=".", recursive=True)
|
|
||||||
#observer.start()
|
|
Reference in a new issue