From 75b3a24aeca3d5797e248d0a5dcf9d6cde85e557 Mon Sep 17 00:00:00 2001 From: Philip Trauner Date: Thu, 20 Apr 2017 11:05:09 +0200 Subject: [PATCH] Removed Sublime Text plugin --- Sublime/fl0w/CompileHighlight.sublime-syntax | 11 - Sublime/fl0w/Default (Linux).sublime-keymap | 14 - Sublime/fl0w/Default (OSX).sublime-keymap | 14 - Sublime/fl0w/Default (Windows).sublime-keymap | 14 - Sublime/fl0w/Shared | 1 - Sublime/fl0w/SublimeMenu.py | 140 ---- Sublime/fl0w/fl0w.py | 756 ------------------ Sublime/fl0w/fl0w.sublime-commands | 6 - Sublime/fl0w/fl0w.sublime-settings | 4 - 9 files changed, 960 deletions(-) delete mode 100644 Sublime/fl0w/CompileHighlight.sublime-syntax delete mode 100644 Sublime/fl0w/Default (Linux).sublime-keymap delete mode 100644 Sublime/fl0w/Default (OSX).sublime-keymap delete mode 100644 Sublime/fl0w/Default (Windows).sublime-keymap delete mode 120000 Sublime/fl0w/Shared delete mode 100644 Sublime/fl0w/SublimeMenu.py delete mode 100644 Sublime/fl0w/fl0w.py delete mode 100644 Sublime/fl0w/fl0w.sublime-commands delete mode 100644 Sublime/fl0w/fl0w.sublime-settings diff --git a/Sublime/fl0w/CompileHighlight.sublime-syntax b/Sublime/fl0w/CompileHighlight.sublime-syntax deleted file mode 100644 index 3e997dc..0000000 --- a/Sublime/fl0w/CompileHighlight.sublime-syntax +++ /dev/null @@ -1,11 +0,0 @@ -%YAML 1.2 ---- -# http://www.sublimetext.com/docs/3/syntax.html -name: Compile Highlight -file_extensions: [] -hidden: true -scope: source.inspect -contexts: - main: - - match: \b(warning|error)\b - scope: keyword.control.c \ No newline at end of file diff --git a/Sublime/fl0w/Default (Linux).sublime-keymap b/Sublime/fl0w/Default (Linux).sublime-keymap deleted file mode 100644 index 00b52dc..0000000 --- a/Sublime/fl0w/Default (Linux).sublime-keymap +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "keys" : ["f8"], - "command" : "run" - }, - { - "keys" : ["f9"], - "command" : "stop" - }, - { - "keys" : ["f10"], - "command" : "sensor" - } -] \ No newline at end of file diff --git a/Sublime/fl0w/Default (OSX).sublime-keymap b/Sublime/fl0w/Default (OSX).sublime-keymap deleted file mode 100644 index 00b52dc..0000000 --- a/Sublime/fl0w/Default (OSX).sublime-keymap +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "keys" : ["f8"], - "command" : "run" - }, - { - "keys" : ["f9"], - "command" : "stop" - }, - { - "keys" : ["f10"], - "command" : "sensor" - } -] \ No newline at end of file diff --git a/Sublime/fl0w/Default (Windows).sublime-keymap b/Sublime/fl0w/Default (Windows).sublime-keymap deleted file mode 100644 index 00b52dc..0000000 --- a/Sublime/fl0w/Default (Windows).sublime-keymap +++ /dev/null @@ -1,14 +0,0 @@ -[ - { - "keys" : ["f8"], - "command" : "run" - }, - { - "keys" : ["f9"], - "command" : "stop" - }, - { - "keys" : ["f10"], - "command" : "sensor" - } -] \ No newline at end of file diff --git a/Sublime/fl0w/Shared b/Sublime/fl0w/Shared deleted file mode 120000 index 8c1ab6a..0000000 --- a/Sublime/fl0w/Shared +++ /dev/null @@ -1 +0,0 @@ -../../Shared \ No newline at end of file diff --git a/Sublime/fl0w/SublimeMenu.py b/Sublime/fl0w/SublimeMenu.py deleted file mode 100644 index 8ff2c59..0000000 --- a/Sublime/fl0w/SublimeMenu.py +++ /dev/null @@ -1,140 +0,0 @@ -FUNCTION = type(lambda: 1) - -class Input: - def __init__(self, caption, initial_text="", on_done=None, on_change=None, - on_cancel=None, kwargs={}): - self.caption = caption - self.initial_text = initial_text - self.on_done = on_done - self.on_change = on_change - self.on_cancel = on_cancel - self.kwargs = kwargs - - - def wrapped_on_done(self, input_): - if not self.on_done == None: - self.on_done(input_, **self.kwargs) - - - def wrapped_on_change(self, input_): - if not self.on_change == None: - self.on_change(input_, **self.kwargs) - - - def wrapped_on_cancel(self): - if not self.on_cancel == None: - self.on_cancel(**self.kwargs) - - - def invoke(self, window): - window.show_input_panel(self.caption, self.initial_text, - self.wrapped_on_done, self.wrapped_on_change, - self.wrapped_on_cancel) - - -class Entry: - def __init__(self, name, description="", action=None, kwargs={}, - sub_menu=None, input=None): - self.name = name - self.description = description - self.action = action - self.kwargs = kwargs - self.sub_menu = sub_menu - self.input = input - - def __eq__(self, other): - return self.__dict__ == other.__dict__ - - -class Menu: - def __init__(self, selected_index=-1, on_highlight=None, subtitles=True): - self.selected_index = selected_index - self.on_highlight = on_highlight - self.subtitles = subtitles - self.entries = {} - self.window = None - self.back = None - - def invoke(self, window, back=None): - self.window = window - self.back = back - entries = self.menu_entries - if back: - entries.insert(0, ["Back", - "Back to previous menu"] if self.subtitles else ["Back"]) - window.show_quick_panel(entries, self._action, - flags=0, selected_index=self.selected_index, - on_highlight=self.on_highlight) - - def _action(self, entry_id): - if entry_id != -1: - if self.back: - if entry_id != 0: - entry = self.entries[entry_id - 1] - else: - self.back.invoke(self.window, back=self.back.back) - return - else: - entry = self.entries[entry_id] - if entry.action != None: - entry.action(**entry.kwargs) - if entry.input != None: - entry.input.invoke(self.window) - if type(entry.sub_menu) is FUNCTION: - entry.sub_menu(entry).invoke(self.window, back=self) - elif entry.sub_menu != None: - entry.sub_menu.invoke(self.window, back=self) - - - @property - def menu_entries(self): - entries = [] - for entry_id in self.entries: - if self.subtitles: - entries.append([self.entries[entry_id].name, self.entries[entry_id].description]) - else: - entries.append([self.entries[entry_id].name]) - return entries - - - def __add__(self, other): - try: - self.add(other) - except TypeError: - return NotImplemented - return self - - - def __sub__(self, other): - try: - self.remove(other) - except TypeError: - return NotImplemented - return self - - - def add(self, entry): - if entry.__class__ == Entry: - if len(self.entries) > 0: - entry_id = tuple(self.entries.keys())[-1] + 1 - else: - entry_id = 0 - self.entries[entry_id] = entry - else: - raise TypeError("invalid type supplied") - - - def remove(self, entry): - if entry.__class__ == Entry: - if entry in self.entries.values(): - found_entry_id = None - for entry_id in self.entries: - if self.entries[entry_id] == entry: - found_entry_id = entry_id - if found_entry_id != None: - del self.entries[entry_id] - else: - raise TypeError("invalid type supplied") - - def clear(self): - self.entries = {} diff --git a/Sublime/fl0w/fl0w.py b/Sublime/fl0w/fl0w.py deleted file mode 100644 index 1250eef..0000000 --- a/Sublime/fl0w/fl0w.py +++ /dev/null @@ -1,756 +0,0 @@ -from sys import path -import os -from time import strftime -from functools import partial -import re - -fl0w_path = os.path.dirname(os.path.realpath(__file__)) -shared_path = os.path.dirname(os.path.realpath(__file__)) + "/Shared/" -if fl0w_path not in path: - path.append(fl0w_path) -if shared_path not in path: - path.append(shared_path) - - -import sublime -import sublime_plugin - -from Highway import Client, Route, Pipe, DummyPipe -from Utils import get_hostname, get_ip_from_url - -import behem0th - -from SublimeMenu import * -import Logging - -import webbrowser -import threading -from time import sleep -import os - -CHANNEL = 1 -FL0W_STATUS = "fl0w" - -def plugin_unloaded(): - for window in windows: - if hasattr(window, "fl0w") and window.fl0w.connected: - window.fl0w.invoke_disconnect() - for sensor_type in ("analog", "digital"): - window.active_view().erase_phantoms(sensor_type) - - -PARENTHESES_REGEX = re.compile("\((.*?)\)") -STYLE_OPEN = "" -STYLE_CLOSE = "" - -ERROR_OPEN = "" -ERROR_CLOSE = "" - -windows = [] -views = [] -sensor_phantoms = [] - -def set_status(status, window): - window.active_view().set_status(FL0W_STATUS, - "fl0w: %s" % status) - -class Target: - def __init__(self, id_, name): - self.id = id_ - self.name = name - - -class Fl0wClient(Client): - def setup(self, routes, fl0w, debug=False): - super().setup(routes, debug=debug) - self.fl0w = fl0w - - - def ready(self): - self.fl0w.connected = True - if self.fl0w.debug: - Logging.info("Connection ready!") - # Enlist on editor channel - self.send({"channel" : CHANNEL, "name" : get_hostname()}, "subscribe") - # Subscribe to controller channel - self.send({"subscribe" : [2]}, "peers") - - - def closed(self, code, reason): - self.fl0w.invoke_disconnect() - if self.fl0w.debug: - Logging.info("Connection closed: %s (%s)" % (reason, code)) - - - def peer_unavaliable(self, peer): - sublime.error_message("The specifed controller is not connected anymore.") - if self.fl0w.target.id == peer: - self.fl0w.target = None - - - class Info(Route): - def run(self, data, handler): - info = "" - for key in data: - info += "%s: %s\n" % (key.capitalize(), ", ".join(data[key])) - sublime.message_dialog(info) - handler.fl0w.meta.invoke(handler.fl0w.window, back=handler.fl0w.main_menu) - - - class Sensor(Pipe): - def run(self, data, peer, handler): - handler.fl0w.subscriptions_lock.acquire() - for sensor_phantom in handler.fl0w.subscriptions: - sensor_phantom.update_sensor_values(data) - handler.fl0w.subscriptions_lock.release() - - - class Peers(Route): - def start(self, handler): - self.selected_action_menu = None - - def run(self, data, handler): - handler.fl0w.controller_menu.clear() - if handler.fl0w.target != None: - if not handler.fl0w.target.id in data: - handler.fl0w.target = None - for id_ in data: - action_menu = Menu() - power_menu = Menu() - utilities_menu = Menu() - action_menu.id_ = id_ - action_menu.name = data[id_]["name"] - action_menu += Entry("Set Target", - "Set controller as target for program execution and sensor readouts", - action=partial(self.set_target, - handler, id_, data[id_]["name"])) - action_menu += Entry("Run program", - "Run a botball program on the controller", - action=partial(handler.pipe, None, "list_programs", id_)) - action_menu += Entry("Stop programs", - "Stop all currently running botball programs", - action=partial(handler.pipe, None, "stop_programs", id_)) - utilities_menu += Entry("Set Name", - "Sets the hostname of the selected controller", - action=partial(lambda handler, id_: Input("New Hostname:", - initial_text=data[id_]["name"], - on_done=lambda hostname: handler.pipe( - {"set" : hostname}, - "hostname", id_)).invoke(handler.fl0w.window), handler, id_)) - utilities_menu += Entry("Processes", - "Lists processes currently running on controller", - action=partial(handler.pipe, None, "processes", id_)) - utilities_menu += Entry("Identify", - "Plays an identification sound on the controller.", - action=partial(handler.pipe, None, "identify", id_)) - action_menu += Entry("Utilities", "Stuff you might need but probably won't", - sub_menu=utilities_menu) - power_menu += Entry("Shutdown", - "Shutdown the controller", - action=partial(handler.pipe, None, "shutdown", id_)) - power_menu += Entry("Reboot", - "Reboot the controller", - action=partial(handler.pipe, None, "reboot", id_)) - action_menu += Entry("Power", "Power related actions", sub_menu=power_menu) - action_menu.back = handler.fl0w.controller_menu - handler.fl0w.controller_menu += Entry(data[id_]["name"], id_, sub_menu=action_menu, - action=self.set_selected_action_menu, - kwargs={"selected_action_menu" : action_menu}) - - - def set_target(self, handler, peer, name): - handler.fl0w.target = Target(peer, name) - if handler.fl0w.debug: - set_status("Target: %s" % peer, handler.fl0w.window) - - - def set_selected_action_menu(self, selected_action_menu): - self.selected_action_menu = selected_action_menu - - - class Processes(Pipe): - def run(self, data, peer, handler): - view = handler.fl0w.window.new_file() - view.set_name("Processes") - view.settings().set("draw_indent_guides", False) - for line in data: - view.run_command("append", {"characters": line + "\n"}) - view.set_read_only(True) - - - class ListPrograms(Pipe): - def run(self, data, peer, handler): - program_menu = Menu(subtitles=False) - for program in data: - program_menu += Entry(program, - action=partial(self.run_program, - handler, handler.routes["peers"].selected_action_menu.id_, - program)) - program_menu.invoke(handler.fl0w.window, - back=handler.routes["peers"].selected_action_menu) - - def run_program(self, handler, id_, program): - handler.pipe(program, "run_program", id_) - - - class RunProgram(Pipe): - PROGRAM_NOT_FOUND = 1 - - def run(self, data, peer, handler): - if data == self.__class__.PROGRAM_NOT_FOUND: - sublime.error_message("Program not found.") - - - class StopPrograms(Pipe): - NO_PROGRAMS_RUNNING = 1 - - def run(self, data, peer, handler): - if data == self.__class__.NO_PROGRAMS_RUNNING: - sublime.error_message("No programs running.") - - - class StdStream(Pipe): - def start(self, handler): - self.output_panels = {} - - self.lock = threading.RLock() - self.buffer = {} - - self.handler = None - - self.fetcher = self.Fetcher(self.buffer, self.write_to_panel, - self.lock) - self.fetcher.start() - - - def create_output_panel(self, window, peer): - view = window.create_output_panel(peer) - view.settings().set("draw_white_space", False) - view.settings().set("draw_indent_guides", False) - view.settings().set("gutter", False) - view.settings().set("line_numbers", False) - view.set_read_only(True) - return view - - - def run(self, data, peer, handler): - self.handler = handler - if type(data) is str: - self.lock.acquire() - # try/except is faster than an explicit if as long as the - # condition is not met - try: - self.buffer[peer].append(data) - except KeyError: - self.buffer[peer] = [] - self.create_output_panel(handler.fl0w.window, peer) - self.output_panels[peer] = self.create_output_panel(handler.fl0w.window, peer) - self.buffer[peer].append(data) - self.lock.release() - # Meta info comes in so infrequently that the conditional logic would - # slow down the regular output streaming - elif type(data) is dict: - meta_text = "" - if "exit_code" in data: - meta_text += "Program finished with exit code: %d\n" % data["exit_code"] - self.lock.acquire() - # try/except is faster than an explicit if as long as the - # condition is not met - # function call is also slower - try: - self.buffer[peer].append(meta_text) - except KeyError: - self.buffer[peer] = [] - self.create_output_panel(handler.fl0w.window, peer) - self.output_panels[peer] = self.create_output_panel(handler.fl0w.window, peer) - self.buffer[peer].append(meta_text) - self.lock.release() - - - - def write_to_panel(self, text, peer): - self.output_panels[peer].set_read_only(False) - self.output_panels[peer].run_command("append", {"characters": text, "scroll_to_end" : True}) - self.output_panels[peer].set_read_only(True) - self.handler.fl0w.window.run_command("show_panel", {"panel": "output.%s" % peer}) - - - # Sublime gets quite overwhelmed when faced with typical - # "while (1) { printf(...)}" output. - # That's why instead of directly writing to the view all received text - # is bundled together after a fixed period of time. - class Fetcher(threading.Thread): - def __init__(self, buffer, write_to_panel, lock, push_rate=0.2): - threading.Thread.__init__(self) - self.buffer = buffer - self.write_to_panel = write_to_panel - self.lock = lock - self.push_rate = push_rate - self.daemon = True - - def run(self): - while True: - self.lock.acquire() - for peer in self.buffer: - if len(self.buffer[peer]) > 0: - self.write_to_panel( - "".join(self.buffer[peer]), - peer) - self.buffer[peer] = [] - self.lock.release() - sleep(self.push_rate) - - -class Fl0w: - def __init__(self, window, debug=False): - self.settings = sublime.load_settings("fl0w.sublime-settings") - self.window = window - self.folder = window.folders()[0] - if self.folder != "/": - self.folder = self.folder + "/" - - self.connected = False - - self.subscriptions = {} - self.subscriptions_lock = threading.Lock() - self._combined_subscriptions = {"analog" : [], "digital" : []} - - self._target = None - self._debug = debug - - - self.start_menu = Menu() - self.start_menu += Entry("Connect", "Connect to a fl0w server", - action=partial(Input("Address:Port (auto-connect nyi)", - initial_text=self.settings.get("address", "127.0.0.1:3077"), - on_done=self.invoke_connect).invoke, self.window)) - self.start_menu += Entry("About", "Information about fl0w", - action=self.invoke_about) - - self.debug_menu = Menu(subtitles=False) - self.debug_menu += Entry("On", - action=lambda: self.set_debug(True)) - self.debug_menu += Entry("Off", - action=lambda: self.set_debug(False)) - - - self.settings_menu = Menu() - self.settings_menu += Entry("Debug", "Toggle debug mode", - sub_menu=self.debug_menu) - - - self.meta = Menu() - self.meta += Entry("Info", "Server info", - action=lambda: self.ws.send(None, "info")) - self.meta_entry = Entry("Meta", "Debug information about fl0w", - sub_menu=self.meta) - if self.debug: - self.main_menu += self.meta_entry - - - self.main_menu = Menu() - self.controller_menu = Menu() - self.main_menu += Entry("Controllers", "All connected controllers", - sub_menu=self.controller_menu) - self.main_menu += Entry("Settings", "General purpose settings", - sub_menu=self.settings_menu) - self.main_menu += Entry("Disconnect", "Disconnect from server", - action=self.invoke_disconnect) - - self.sync_client = behem0th.Client(path=self.folder, verbose_log=True) - - # Patch all sensor phantom that have been created before a fl0w instance - # was attached to the window - for sensor_phantom in sensor_phantoms: - if sensor_phantom.window.id() == self.window.id(): - sensor_phantom.fl0w = self - if self.debug: - Logging.info("Patched sensor phantom '%s'" % str(sensor_phatom)) - - - @property - def target(self): - return self._target - - - @target.setter - def target(self, target): - if self.target != None: - self.ws.pipe("unsubscribe", "sensor", self.target.id) - self._target = target - if target != None: - set_status("Target: %s (%s)" % (target.name, target.id), self.window) - if self.combined_subscriptions != {"analog" : [], "digital" : []}: - self.ws.pipe({"subscribe" : self.combined_subscriptions}, "sensor", target.id) - else: - set_status("The target has become unavaliable.", self.window) - - - @property - def debug(self): - return self._debug - - - def set_debug(self, debug): - self.debug = debug - - - @debug.setter - def debug(self, debug): - if debug: - self._debug = True - if not self.meta_entry in self.main_menu.entries.values(): - self.main_menu += self.meta_entry - else: - self._debug = False - self.main_menu -= self.meta_entry - set_status("Debug set to %s" % self._debug, self.window) - - - # Could be simplified because only one view can be active at any time. - # This would definetly lead to some major performace improvements on - # view switching and less unnecessary unsubscribes. - - # On the other hand it might be a good idea to leave it in and provide - # an option to disable aggressive unsubscribes - @property - def combined_subscriptions(self): - return self._combined_subscriptions - - - @combined_subscriptions.setter - def combined_subscriptions(self, combined_subscriptions_): - if self.combined_subscriptions != combined_subscriptions_: - self._combined_subscriptions = combined_subscriptions_ - if self.connected and self.target != None: - self.ws.pipe("unsubscribe", "sensor", self.target.id) - if combined_subscriptions_ != {"analog" : [], "digital" : []}: - self.ws.pipe({"subscribe" : combined_subscriptions_}, "sensor", - self.target.id) - - - def subscribe(self, sensor_phatom, subscriptions): - self.subscriptions_lock.acquire() - self.subscriptions[sensor_phatom] = subscriptions - self.subscriptions_lock.release() - self.make_subscriptions() - - - - def unsubscribe(self, sensor_phantom): - if sensor_phantom in self.subscriptions: - """ - print("Lock will be aquired.") - self.subscriptions_lock.acquire() - print("Lock was aquired.") - del self.subscriptions[sensor_phantom] - print("Lock will be released.") - self.subscriptions_lock.release() - print("Lock was released.") - """ - # Temporary solution, locking caused sublime to freeze - # Could cause problems if lots (> 100) views are open. - self.subscriptions[sensor_phantom] = {"analog" : [], "digital" : []} - self.make_subscriptions() - - - def make_subscriptions(self): - combined_subscriptions = {"analog" : [], "digital" : []} - for sensor_phantom in self.subscriptions: - for sensor_type in ("analog", "digital"): - combined_subscriptions[sensor_type] = list( - set(combined_subscriptions[sensor_type]) | - set(self.subscriptions[sensor_phantom][sensor_type]) - ) - self.combined_subscriptions = combined_subscriptions - - - def run_program(self, path): - if self.connected and self.target != None: - relpath = os.path.relpath(path, self.folder) - if os.path.isfile(self.folder + relpath): - if self.debug: - Logging.info("Running program '%s'" % relpath) - self.ws.pipe(relpath.rstrip(".c"), "run_program", self.target.id) - - - def stop_programs(self): - if self.connected and self.target != None: - self.ws.pipe(None, "stop_programs", self.target.id) - - - def invoke_start_menu(self): - self.start_menu.invoke(self.window) - - - def invoke_main_menu(self): - self.main_menu.invoke(self.window) - - - def invoke_about(self): - if sublime.ok_cancel_dialog("fl0w by @robot0nfire", "robot0nfire.com"): - webbrowser.open("http://robot0nfire.com") - - - def connect(self, address): - try: - self.ws = Fl0wClient(address) - self.ws.setup({"info" : Fl0wClient.Info(), "peers" : Fl0wClient.Peers(), - "processes" : Fl0wClient.Processes(), - "list_programs" : Fl0wClient.ListPrograms(), "sensor" : Fl0wClient.Sensor(), - "std_stream" : Fl0wClient.StdStream(), "run_program" : Fl0wClient.RunProgram(), - "stop_programs" : Fl0wClient.StopPrograms()}, - self, debug=True) - self.ws.connect() - sublime.set_timeout_async(self.ws.run_forever, 0) - set_status("Connection opened '%s'" % self.folder, self.window) - self.connected = True - self.settings.set("address", address) - self.sync_client.connect(get_ip_from_url(address)) - - except (OSError, ConnectionRefusedError) as e: - sublime.error_message("Error during connection creation:\n %s" % str(e)) - - - - def invoke_connect(self, address): - # Will be removed once autoconnect works - self.connect("ws://%s" % address) - - - def invoke_disconnect(self): - if self.connected: - for sensor_phantom in sensor_phantoms: - if sensor_phantom.window.id() == self.window.id(): - sensor_phantom.enabled = False - self.target = None - self.ws.close() - set_status("Connection closed '%s'" % self.folder, self.window) - self.connected = False - - self.sync_client.close() - - -class Fl0wCommand(sublime_plugin.WindowCommand): - def run(self): - valid_window_setup = True - folder_count = len(self.window.folders()) - if folder_count > 1: - sublime.error_message("Only one open folder per window is allowed.") - valid_window_setup = False - elif folder_count == 0: - sublime.error_message("No folder open in window.") - valid_window_setup = False - if valid_window_setup: - if not hasattr(self.window, "fl0w"): - folder = self.window.folders()[0] - files = os.listdir(folder) - if not ".no-fl0w" in files: - if not ".fl0w" in files: - open(folder + "/.fl0w", 'a').close() - self.window.fl0w = Fl0w(self.window) - windows.append(self.window) - self.window.fl0w.start_menu.invoke(self.window) - else: - self.window.fl0w = Fl0w(self.window) - windows.append(self.window) - self.window.fl0w.start_menu.invoke(self.window) - else: - sublime.error_message("fl0w can't be opened in your current directory (.no-fl0w file exists)") - else: - if not self.window.fl0w.connected: - self.window.fl0w.invoke_start_menu() - else: - self.window.fl0w.invoke_main_menu() - else: - if hasattr(self.window, "fl0w"): - sublime.error_message("Window setup was invalidated (Don't close or open any additional folders in a fl0w window)") - self.window.fl0w.invoke_disconnect() - - -class RunCommand(sublime_plugin.WindowCommand): - def run(self): - if hasattr(self.window, "fl0w"): - if self.window.fl0w.connected: - if self.window.fl0w.target == None: - sublime.error_message("A target controller has to be set to " - "run programs.") - else: - file_name = self.window.active_view().file_name() - if file_name != None and file_name.endswith(".c"): - self.window.fl0w.run_program(file_name) - else: - sublime.error_message("fl0w is not connected.") - else: - sublime.error_message("fl0w is not running in your current window.") - -class StopCommand(sublime_plugin.WindowCommand): - def run(self): - if hasattr(self.window, "fl0w"): - if self.window.fl0w.connected: - if self.window.fl0w.target == None: - sublime.error_message("A target controller has to be set to " - "stop programs.") - else: - self.window.fl0w.stop_programs() - else: - sublime.error_message("fl0w is not connected.") - else: - sublime.error_message("fl0w is not running in your current window.") - - -class SensorCommand(sublime_plugin.WindowCommand): - def run(self): - if hasattr(self.window, "fl0w"): - if self.window.fl0w.connected: - if self.window.fl0w.target == None: - sublime.error_message("A target controller has to be set to " - "enable inline sensor readouts.") - else: - view_id = self.window.active_view().id() - for view in views: - if view.id() == view_id: - view.sensor_phantom.enabled = not view.sensor_phantom.enabled - view_file_name = view.file_name() - if view_file_name == None: - view_file_name = "untitled" - set_status("%s sensor phantoms for '%s'." % ( - "Enabled" if view.sensor_phantom.enabled else "Disabled", - view_file_name), - self.window) - else: - sublime.error_message("fl0w is not connected.") - else: - sublime.error_message("fl0w is not running in your current window.") - - - -class SensorPhantom(sublime_plugin.ViewEventListener): - def __init__(self, view): - self.view = view - self.view.sensor_phantom = self - if not view in views: - views.append(view) - self.window = view.window() - - # Is patched by the fl0w instance that is in control of the same window - self.fl0w = None - self._enabled = False - - self.previously_enabled = False - - self._matches = {"analog" : [], "digital" : []} - - self.timeout_scheduled = False - self.needs_update = False - - for window in windows: - if hasattr(window, "fl0w"): - self.fl0w = window.fl0w - if not self in sensor_phantoms: - sensor_phantoms.append(self) - - - @property - def enabled(self): - return self._enabled - - - @enabled.setter - def enabled(self, enabled_): - if enabled_: - if self.fl0w != None: - self.find_matches() - self.fl0w.subscribe(self, self.subscriptions) - self._enabled = True - else: - if self.fl0w != None: - self.fl0w.unsubscribe(self) - for sensor_type in ("analog", "digital"): - self.view.erase_phantoms(sensor_type) - self._enabled = False - - - @property - def matches(self): - return self._matches - - @matches.setter - def matches(self, matches_): - if not matches_ == self.matches: - self._matches = matches_ - self.fl0w.subscribe(self, self.subscriptions) - - - @property - def subscriptions(self): - subscriptions_ = {"analog" : [], "digital" : []} - for sensor_type in ("analog", "digital"): - subscriptions_[sensor_type] = [sensor[0] for sensor in self.matches[sensor_type]] - return subscriptions_ - - - def find_matches(self): - matches = {"analog" : [], "digital" : []} - # Don't do any calculations on 1MB or larger files - if self.view.size() < 2**20: - for method_name in ("analog", "digital"): - candidates = self.view.find_all("%s\(\d*\)" % method_name) - for candidate in candidates: - line = self.view.substr(candidate) - port_candidates = re.findall(PARENTHESES_REGEX, line) - if len(port_candidates) == 1: - if port_candidates[0].isnumeric(): - matches[method_name].append( - ( - int(port_candidates[0]), - sublime.Region(self.view.line(candidate.a).b) - )) - self.matches = matches - - # Called by fl0w instance - def update_sensor_values(self, readouts): - for sensor_type in ("analog", "digital"): - self.view.erase_phantoms(sensor_type) - for match in self.matches[sensor_type]: - try: - self.view.add_phantom(sensor_type, match[1], - STYLE_OPEN + str(readouts[sensor_type][str(match[0])]) + STYLE_CLOSE, - sublime.LAYOUT_INLINE) - except KeyError: - self.view.add_phantom(sensor_type, match[1], - ERROR_OPEN + "!" + ERROR_CLOSE, - sublime.LAYOUT_INLINE) - - - def handle_timeout(self): - self.timeout_scheduled = False - if self.needs_update: - self.needs_update = False - self.find_matches() - - - def on_modified(self): - if self.enabled: - if self.timeout_scheduled: - self.needs_update = True - else: - sublime.set_timeout(lambda: self.handle_timeout(), 500) - self.find_matches() - - - - def on_deactivated(self): - self.previously_enabled = self.enabled - if self.enabled: - self.enabled = False - - def on_activated(self): - if not self.enabled and self.previously_enabled: - self.enabled = True - - - def __del__(self): - self.enabled = False - if self in sensor_phantoms: - del sensor_phantoms[sensor_phantoms.index(self)] diff --git a/Sublime/fl0w/fl0w.sublime-commands b/Sublime/fl0w/fl0w.sublime-commands deleted file mode 100644 index a2b89be..0000000 --- a/Sublime/fl0w/fl0w.sublime-commands +++ /dev/null @@ -1,6 +0,0 @@ -[ - { - "caption": "fl0w: Menu", - "command": "fl0w" - } -] \ No newline at end of file diff --git a/Sublime/fl0w/fl0w.sublime-settings b/Sublime/fl0w/fl0w.sublime-settings deleted file mode 100644 index 51a7f3b..0000000 --- a/Sublime/fl0w/fl0w.sublime-settings +++ /dev/null @@ -1,4 +0,0 @@ -{ - "server_address": "", // Last server address - "compression_level": 2 -}