|
| 1 | +import sublime |
| 2 | +import time |
| 3 | +import sublime_plugin |
| 4 | +import webbrowser |
| 5 | +import subprocess |
| 6 | +import atexit |
| 7 | +import re |
| 8 | +from .MarkmonListener import MarkmonListener |
| 9 | +import http.client |
| 10 | +from . import util |
| 11 | +import os |
| 12 | +from threading import Timer |
| 13 | + |
| 14 | +MARKDOWN_SYNTAX = re.compile(r'.*[Mm]arkdown.*') |
| 15 | + |
| 16 | +markmon = None |
| 17 | +def plugin_loaded(): |
| 18 | + """The ST3 entry point for plugins.""" |
| 19 | + global markmon |
| 20 | + markmon = Markmon(MarkmonListener.shared_plugin()) |
| 21 | + |
| 22 | +class Markmon: |
| 23 | + def __init__(self, listener): |
| 24 | + listener = MarkmonListener.shared_plugin() |
| 25 | + listener.load_settings() |
| 26 | + |
| 27 | + self.settings = MarkmonSettings() |
| 28 | + self.client = MarkmonClient(self.settings) |
| 29 | + self.server = MarkmonServer(self.settings) |
| 30 | + self.client.set_server(self.server) |
| 31 | + |
| 32 | + listener.add_on_settings_change(self.settings_updated) |
| 33 | + listener.add_on_modified(self.client.view_updated) |
| 34 | + |
| 35 | + def settings_updated(self, settings): |
| 36 | + self.settings.update(settings) |
| 37 | + self.server.setup_server() |
| 38 | + |
| 39 | + def display(self): |
| 40 | + current_view = sublime.active_window().active_view() |
| 41 | + self.client.view_updated(current_view) |
| 42 | + webbrowser.open("http://" + self.settings.client_url) |
| 43 | + |
| 44 | + def set_running(self, running): |
| 45 | + if running != self.settings.running: |
| 46 | + self.settings.running = running |
| 47 | + if running: |
| 48 | + self.server.setup_server() |
| 49 | + # need a delay to wait for the server to set up |
| 50 | + Timer(1.0, self.display).start() |
| 51 | + else: |
| 52 | + self.server.cleanup_server() |
| 53 | + elif running: |
| 54 | + self.display() |
| 55 | + |
| 56 | + |
| 57 | +class MarkmonSettings: |
| 58 | + def __init__(self): |
| 59 | + self.running = False |
| 60 | + self.settings = {} |
| 61 | + self.server_command = [] |
| 62 | + self.client_url = "" |
| 63 | + |
| 64 | + def update(self, settings): |
| 65 | + self.settings = { |
| 66 | + "port": settings.get("port", 3000), |
| 67 | + "command": settings.get("command", "pandoc -t HTML5"), |
| 68 | + "stylesheet": settings.get("stylesheet", None), |
| 69 | + "projectdir": settings.get("projectdir", None) |
| 70 | + } |
| 71 | + self.build_strings() |
| 72 | + |
| 73 | + def build_strings(self): |
| 74 | + self.client_url = "localhost:{:d}".format(self.settings['port']) |
| 75 | + self.server_command = ['markmon', |
| 76 | + "--port", str(self.settings['port']), |
| 77 | + "--command", self.settings['command']] |
| 78 | + if self.settings['stylesheet']: |
| 79 | + self.server_command.append("--stylesheet") |
| 80 | + self.server_command.append(self.settings['stylesheet']) |
| 81 | + |
| 82 | + if self.settings['projectdir']: |
| 83 | + self.server_command.append("--projectdir") |
| 84 | + self.server_command.append(self.settings['projectdir']) |
| 85 | + |
| 86 | +class MarkmonClient: |
| 87 | + def __init__(self, settings): |
| 88 | + self.settings = settings |
| 89 | + self.server = None |
| 90 | + |
| 91 | + def set_server(self, server): |
| 92 | + self.server = server |
| 93 | + |
| 94 | + def view_updated(self, view, try_server=True): |
| 95 | + if self.settings.running and MARKDOWN_SYNTAX.match(view.scope_name(0)): |
| 96 | + try: |
| 97 | + connection = http.client.HTTPConnection(self.settings.client_url) |
| 98 | + connection.request('PUT', '/', view.substr(sublime.Region(0, view.size()))) |
| 99 | + connection.getresponse() |
| 100 | + except ConnectionRefusedError: |
| 101 | + if self.server: |
| 102 | + if try_server: |
| 103 | + self.server.setup_server() |
| 104 | + time.sleep(1) |
| 105 | + self.view_updated(view, False) |
| 106 | + else: |
| 107 | + print("Markmon server is down. Check your preferences.") |
| 108 | + |
| 109 | +class MarkmonServer: |
| 110 | + def __init__(self, settings): |
| 111 | + self.server_url = None |
| 112 | + self.settings = settings |
| 113 | + atexit.register(self.cleanup_server) |
| 114 | + |
| 115 | + def setup_server(self, _=None): |
| 116 | + try: |
| 117 | + self.cleanup_server() |
| 118 | + except: |
| 119 | + pass |
| 120 | + if not self.settings.running: |
| 121 | + return |
| 122 | + self.server_url = self.settings.client_url |
| 123 | + env = os.environ.copy() |
| 124 | + betterenv = util.create_environment() |
| 125 | + env["PATH"] = betterenv["PATH"] |
| 126 | + subprocess.Popen(self.settings.server_command, env=env) |
| 127 | + |
| 128 | + def cleanup_server(self): |
| 129 | + if self.server_url: |
| 130 | + connection = http.client.HTTPConnection(self.server_url) |
| 131 | + connection.request('DELETE', '/') |
| 132 | + connection.getresponse() |
0 commit comments