From 106f99154ffcc2fc27cd7c24cb02511af8f5ae46 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Tue, 27 Feb 2024 19:12:27 -0500 Subject: [PATCH 01/12] fixed version issues except for the Windows ones --- Default.sublime-keymap | 1 + Main.sublime-menu | 39 +++++++++++++++++++- README.md | 5 ++- __init__.py | 48 +++++++++++++++++++------ src/completion_text.py | 13 ++++++- src/phantom_state.py | 6 ++-- src/refact_lsp.py | 80 ++++++++++++++++++++++++++++++++++-------- src/refact_process.py | 29 +++++---------- src/refact_sessions.py | 30 ++++++++++++++-- src/statusbar.py | 14 +++++++- src/utils.py | 7 ++++ 11 files changed, 216 insertions(+), 56 deletions(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 9a5da6c..3385a62 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -1,4 +1,5 @@ [ { "keys": ["tab"], "command": "refact_accept_completion", "context": [{"key": "refact.show_completion"}] }, { "keys": ["escape"], "command": "refact_clear_completion", "context": [{"key": "refact.show_completion"}] }, + { "keys": ["ctrl+p"], "command": "refact_pause" } ] diff --git a/Main.sublime-menu b/Main.sublime-menu index 47cdcfe..d5ef9a4 100644 --- a/Main.sublime-menu +++ b/Main.sublime-menu @@ -9,5 +9,42 @@ "args":{} }, ] - } + }, + { + "caption": "Preferences", + "mnemonic": "n", + "id": "preferences", + "children": + [ + { + "caption": "Package Settings", + "mnemonic": "P", + "id": "package-settings", + "children": + [ + { + "caption": "refact", + "children": + [ + { + "command": "open_file", "args": + { + "file": "${packages}/refact/refact.sublime-settings" + }, + "caption": "Settings – Default" + }, + { + "command": "open_file", "args": + { + "file": "${packages}/User/refact.sublime-settings" + }, + "caption": "Settings – User" + }, + { "caption": "-" } + ] + } + ] + } + ] + } ] diff --git a/README.md b/README.md index 76696b0..e48af24 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ Refact for VS Code is a free, open-source AI code assistant 4. Move the folder repsository to sublime's "Packages" folder (you can find this by opening the command prompt in sublime and typing "browse packages") 5. rename the folder to "refact" 6. Open refact.sublime-settings and add the API key - + +#Pause +You can pause and unpause refact suggestions by pressing ctrl + p + #File Documentation# #__init__.py diff --git a/__init__.py b/__init__.py index 438ffce..b52d6d6 100644 --- a/__init__.py +++ b/__init__.py @@ -21,7 +21,20 @@ def on_modified(self, view): session = refact_session_manager.get_session(view) session.notify_document_update() session.update_completion() + + def on_close(self, view): + if not start_refact: + return + + session = refact_session_manager.get_session(view) + session.notify_close() + def on_post_save(self, view): + if not start_refact: + return + + session = refact_session_manager.get_session(view) + session.notify_save() def on_query_context(self, view, key, operator, operand, match_all): if start_refact: @@ -52,6 +65,7 @@ def on_text_command(self, view, command_name, args): elif command_name == "hide_popup": session.clear_completion() # elif command_name == "left_delete" or command_name == "right_delete": + # session.clear_completion() elif command_name == "move" or command_name == "move_to": session.clear_completion() @@ -63,17 +77,24 @@ def plugin_loaded(): global start_refact s = sublime.load_settings("refact.sublime-settings") pause_completion = s.get("pause_completion", False) - if not pause_completion: + if pause_completion: + sublime.status_message("⏸️ refact.ai") + else: + refact_start() + +def refact_start(): + global refact_session_manager + global start_refact + if refact_session_manager: + refact_session_manager.start() + else: refact_session_manager = RefactSessionManager() - start_refact= True + start_refact= True class RefactStartCommand(sublime_plugin.TextCommand): def run(self, edit): - global refact_session_manager - global start_refact - refact_session_manager = RefactSessionManager() - start_refact= True - + refact_start() + class RefactStopCommand(sublime_plugin.TextCommand): def run(self, edit): global start_refact @@ -123,11 +144,18 @@ def run(self, edit): global start_refact start_refact= False s = sublime.load_settings("refact.sublime-settings") - s.set("pause_completion", True) + pause_status = s.get("pause_completion", False) + pause_status = not pause_status + s.set("pause_completion", pause_status) sublime.save_settings("refact.sublime-settings") - refact_session_manager.get_session(self.view).clear_completion() + + if not pause_status: + refact_start() + else: + if refact_session_manager: + refact_session_manager.shutdown() class RefactClearCompletion(sublime_plugin.TextCommand): def run(self, edit): refact_session_manager.get_session(self.view).clear_completion() - + diff --git a/src/completion_text.py b/src/completion_text.py index e2198b5..5297b12 100644 --- a/src/completion_text.py +++ b/src/completion_text.py @@ -1,5 +1,6 @@ +from .utils import * -def get_nonwhitespace(s, start): +def get_nonwhitespace(s, start = 0): end = len(s) for i in range(start, end): if not s[i].isspace(): @@ -43,6 +44,16 @@ def collect_space(s, index): return space def get_completion_text(point, text, line, end = None): + if not line or line.isspace(): + s = replace_tab(text) + res_space = get_nonwhitespace(s) + l = replace_tab(line) + diff = res_space - len(l) + if diff > 0: + return s[(res_space - diff):] + else: + return s[res_space:] + diff = find_diff(text, line) end = end or len(line) diff --git a/src/phantom_state.py b/src/phantom_state.py index cdf3e8b..a8754c6 100644 --- a/src/phantom_state.py +++ b/src/phantom_state.py @@ -55,10 +55,7 @@ def __init__(self, view, phantom_block): self.empty = (not self.cursor_phantom or len(self.cursor_phantom.text) == 0) and not self.next_inline_phantom and not self.next_line_phantom def is_cursor_on_line(self, view, line): - if self.cursor_phantom.line <= view.rowcol(line.b)[0]: - phantom_line = self.cursor_phantom.get_line(view) - return phantom_line.intersects(line) - return False + return self.cursor_phantom.line == view.rowcol(line.b)[0] def create_phantom(self, view, position, text): return PhantomSeed(view, position, text) @@ -218,6 +215,7 @@ def get_update_meta(self, seed): line = view.line(cursor_point) if not seed.is_cursor_on_line(view, line): + self.clear_phantoms() return None completion_text = self.get_seed_completion_text(seed) diff --git a/src/refact_lsp.py b/src/refact_lsp.py index aa53074..90ba084 100644 --- a/src/refact_lsp.py +++ b/src/refact_lsp.py @@ -13,16 +13,24 @@ def __init__(self, process, statusbar): self.connect(process) def load_document(self, file_name: str, text: str, version: int = 1, languageId = LANGUAGE_IDENTIFIER.PYTHON): + print("load_document", file_name) + if languageId is None: languageId = LANGUAGE_IDENTIFIER.PYTHON + if file_name is None: + return + uri = pathlib.Path(file_name).as_uri() try: - self.lsp_client.didOpen(TextDocumentItem(uri, languageId, version, text=text)) - except: + self.lsp_client.didOpen(TextDocumentItem(uri, languageId, version=version, text=text)) + except Exception as err: + self.statusbar.handle_err(err) print("lsp didOpen error") def did_change(self, file_name: str, version: int, text: str, languageId = LANGUAGE_IDENTIFIER.PYTHON): + print("did_change file_name", file_name) + if languageId is None: languageId = LANGUAGE_IDENTIFIER.PYTHON @@ -30,12 +38,49 @@ def did_change(self, file_name: str, version: int, text: str, languageId = LANGU return uri = pathlib.Path(file_name).as_uri() - + try: self.lsp_client.didChange(TextDocumentItem(uri, languageId, version, text=text), [TextDocumentContentChangeEvent(None, None, text)]) - except: + except Exception as err: + self.statusbar.handle_err(err) print("lsp didChange error") + def did_save(self, file_name: str, version: int, text: str, languageId = LANGUAGE_IDENTIFIER.PYTHON): + print("did_save file_name", file_name) + + if languageId is None: + languageId = LANGUAGE_IDENTIFIER.PYTHON + + if file_name is None: + return + + uri = pathlib.Path(file_name).as_uri() + + try: + self.lsp_client.lsp_endpoint.send_notification("textDocument/didSave", textDocument=TextDocumentItem(uri, languageId, version, text=text)) + + except Exception as err: + self.statusbar.handle_err(err) + + print("lsp didChange error", str(err)) + + def did_close(self, file_name: str, version: int, text: str, languageId = LANGUAGE_IDENTIFIER.PYTHON): + print("did_close file_name", file_name) + + if languageId is None: + languageId = LANGUAGE_IDENTIFIER.PYTHON + + if file_name is None: + return + + uri = pathlib.Path(file_name).as_uri() + + try: + self.lsp_client.lsp_endpoint.send_notification("textDocument/didClose", textDocument=TextDocumentItem(uri, languageId, version, text=text)) + except Exception as err: + print("lsp did_close error") + self.statusbar.handle_err(err) + def get_completions(self, file_name, pos: Tuple[int, int], multiline: bool = False): self.statusbar.update_statusbar("loading") params = { @@ -43,8 +88,12 @@ def get_completions(self, file_name, pos: Tuple[int, int], multiline: bool = Fal "temperature": 0.1 } + if file_name is None: + return + uri = pathlib.Path(file_name).as_uri() - try: + + try: res = self.lsp_endpoint.call_method( "refact/getCompletions", textDocument=TextDocumentIdentifier(uri), @@ -54,29 +103,30 @@ def get_completions(self, file_name, pos: Tuple[int, int], multiline: bool = Fal self.statusbar.update_statusbar("ok") return res except Exception as err: - self.statusbar.update_statusbar("error", str(type(err))) + self.statusbar.handle_err(err) def shutdown(self): try: self.lsp_client.shutdown() - except: + except Exception as err: + self.statusbar.handle_err(err) + print("lsp error shutdown") + def logMessage(self, args): + print("logMessage", args) + def connect(self, process): capabilities = {} - # s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) - # s.connect(("127.0.0.1", 8002)) - # pipein, pipeout = s.makefile("wb", buffering=0), s.makefile("rb", buffering=0) - - # json_rpc_endpoint = JsonRpcEndpoint(pipein, pipeout) json_rpc_endpoint = JsonRpcEndpoint(process.stdin, process.stdout) - self.lsp_endpoint = LspEndpoint(json_rpc_endpoint) + self.lsp_endpoint = LspEndpoint(json_rpc_endpoint, notify_callbacks = {"window/logMessage":print}) self.lsp_client = LspClient(self.lsp_endpoint) + try: self.lsp_client.initialize(process.pid, None, None, None, capabilities, "off", None) except Exception as err: - self.statusbar.update_statusbar("error", str(type(err))) - print("lsp initialize error") + self.statusbar.handle_err(err) + print("lsp initialize error", err) def get_language_id(file_type): if file_type and not file_type.isspace(): diff --git a/src/refact_process.py b/src/refact_process.py index 14e121f..5eeaad8 100644 --- a/src/refact_process.py +++ b/src/refact_process.py @@ -12,16 +12,6 @@ def __init__(self): self.active = False self.statusbar = StatusBar() - def process_server_errors(self): - process = self.process - - stderr = self.process.stderr - while process.poll() is None: - line = stderr.readline().decode('utf-8') - print(line) - if "error" in line: - self.statusbar.update_statusbar("error", line) - def get_server_path(self): return os.path.join(sublime.packages_path(), "refact", "server", "refact-lsp") @@ -51,19 +41,16 @@ def get_server_commands(self): def start_server(self): self.active = True server_cmds = self.get_server_commands() - self.process = subprocess.Popen(server_cmds, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE) - self.poll_server() - t = threading.Thread(target=self.process_server_errors) - t.start() - + self.process = subprocess.Popen(server_cmds, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) + + self.statusbar.update_statusbar("ok") if not self.connection is None: self.connection.shutdown() self.connection = LSP(self.process, self.statusbar) - def poll_server(self): - didCrash = self.process.poll() - if not didCrash is None: - self.active = False - else: - sublime.set_timeout(self.poll_server, 100) + def stop_server(self): + self.connection.shutdown() + self.process.terminate() + self.statusbar.update_statusbar("pause") + diff --git a/src/refact_sessions.py b/src/refact_sessions.py index d5f409e..17f2b7c 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -9,6 +9,7 @@ from .refact_lsp import LSP, get_language_id from .refact_process import RefactProcessWrapper from .phantom_state import PhantomState, PhantomInsertion +from .completion_text import get_nonwhitespace class RefactSessionManager: @@ -18,6 +19,15 @@ def __init__(self): self.connection = self.process.start_server() self.views = {} + def start(self): + self.connection = self.process.start_server() + + def shutdown(self): + if self.process and self.process.active: + self.process.stop_server() + for key, session in self.views.items(): + session.clear_completion() + def get_view_id(self, view): if view.element() is None: return view.id() @@ -61,7 +71,17 @@ def notify_document_update(self): if self.is_ui or self.phantom_state.update_step: return self.connection().did_change(self.file_name, self.version, get_text(self.view), self.languageId) - self.version = self.version + 1 + + def notify_close(self): + if self.is_ui or self.phantom_state.update_step: + return + self.connection().did_close(self.file_name, self.version, get_text(self.view), self.languageId) + + def notify_save(self): + if self.is_ui or self.phantom_state.update_step: + return + + self.connection().did_save(self.file_name, self.version, get_text(self.view), self.languageId) def update_completion(self): if self.is_ui : @@ -154,7 +174,13 @@ def show_completions_inner(self, version, prefix, locations, multiline = False): return rc = self.view.rowcol(location) - res = self.connection().get_completions(self.file_name, rc, multiline) + + if not prefix or prefix.isspace(): + pos_arg = (rc[0], 0) + else: + pos_arg = rc + res = self.connection().get_completions(self.file_name, pos_arg, multiline) + if res is None: self.clear_completion_process() return diff --git a/src/statusbar.py b/src/statusbar.py index df7a567..2833c89 100644 --- a/src/statusbar.py +++ b/src/statusbar.py @@ -7,12 +7,14 @@ def __init__(self): self.status_loop() self.icons = [u"◐", u"◓", u"◑", u"◒"] self.current_icon = 0 + self.duration = 0 def status_loop(self): display = "" - if self.status == "error": display = '⛔refact.ai:' + self.msg + elif self.status == "pause": + display ="⏸️ refact.ai" elif self.status == "ok": display = "refact.ai" elif self.status == "loading": @@ -20,8 +22,18 @@ def status_loop(self): self.current_icon = (self.current_icon + 1 ) % len(self.icons) sublime.status_message(display) + if self.duration > 0 or self.status == "loading": + if self.duration > 0: + self.duration = self.duration - 1 sublime.set_timeout(self.status_loop, 100) def update_statusbar(self, status, msg = ""): self.status = status self.msg = msg + self.duration = 5 + self.status_loop() + + def handle_err(self, err): + if not isinstance(err, str) and err.message: + err = err.message + self.update_statusbar("error", msg = str(err)) \ No newline at end of file diff --git a/src/utils.py b/src/utils.py index f7efe4c..3d10aeb 100644 --- a/src/utils.py +++ b/src/utils.py @@ -36,3 +36,10 @@ def filter_none(l): def identity(x): return x + +def replace_tab(text): + s = sublime.load_settings("Preferences.sublime-settings") + tab_size = s.get("tab_size", 4) + return text.replace('\t', ' ' * tab_size) + + From 255ea222ee57c5a295ca4daabd562fffeb67c0a1 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Tue, 27 Feb 2024 20:02:34 -0500 Subject: [PATCH 02/12] fixed windows issues --- Default.sublime-keymap | 2 +- README.md | 2 +- src/refact_process.py | 4 +++- src/refact_sessions.py | 4 ++-- src/statusbar.py | 7 +++++-- 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index 3385a62..c4c8882 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -1,5 +1,5 @@ [ { "keys": ["tab"], "command": "refact_accept_completion", "context": [{"key": "refact.show_completion"}] }, { "keys": ["escape"], "command": "refact_clear_completion", "context": [{"key": "refact.show_completion"}] }, - { "keys": ["ctrl+p"], "command": "refact_pause" } + { "keys": ["ctrl+alt+p"], "command": "refact_pause" } ] diff --git a/README.md b/README.md index e48af24..59c003a 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ Refact for VS Code is a free, open-source AI code assistant 6. Open refact.sublime-settings and add the API key #Pause -You can pause and unpause refact suggestions by pressing ctrl + p +You can pause and unpause refact suggestions by pressing ctrl + alt + p #File Documentation# diff --git a/src/refact_process.py b/src/refact_process.py index 5eeaad8..8b6e02e 100644 --- a/src/refact_process.py +++ b/src/refact_process.py @@ -41,7 +41,9 @@ def get_server_commands(self): def start_server(self): self.active = True server_cmds = self.get_server_commands() - self.process = subprocess.Popen(server_cmds, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + self.process = subprocess.Popen(server_cmds, startupinfo=startupinfo, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) self.statusbar.update_statusbar("ok") if not self.connection is None: diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 17f2b7c..88c36e8 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -54,9 +54,9 @@ def __init__(self, view, connection, is_ui = False): self.file_name = view.file_name() if view.file_name() is None: if is_ui: - self.file_name = "/UI" + self.file_name = os.path.abspath(os.sep) + "UI" else: - self.file_name = "/" + str(time.time()) + "_" + str(view.id()) + self.file_name = os.path.abspath(os.sep) + str(time.time()) + "_" + str(view.id()) self.phantom_state = PhantomState(view) self.connection = connection diff --git a/src/statusbar.py b/src/statusbar.py index 2833c89..e911d87 100644 --- a/src/statusbar.py +++ b/src/statusbar.py @@ -34,6 +34,9 @@ def update_statusbar(self, status, msg = ""): self.status_loop() def handle_err(self, err): - if not isinstance(err, str) and err.message: - err = err.message + if not isinstance(err, str): + if hasattr(err, 'message'): + err = err.message + else: + err = str(err) self.update_statusbar("error", msg = str(err)) \ No newline at end of file From 4ac63e46f9a6c3c21108586f366aedbdb4e21205 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Tue, 27 Feb 2024 20:52:41 -0500 Subject: [PATCH 03/12] Update Default.sublime-keymap --- Default.sublime-keymap | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Default.sublime-keymap b/Default.sublime-keymap index c4c8882..b6c4f7d 100644 --- a/Default.sublime-keymap +++ b/Default.sublime-keymap @@ -1,5 +1,6 @@ [ { "keys": ["tab"], "command": "refact_accept_completion", "context": [{"key": "refact.show_completion"}] }, { "keys": ["escape"], "command": "refact_clear_completion", "context": [{"key": "refact.show_completion"}] }, - { "keys": ["ctrl+alt+p"], "command": "refact_pause" } + { "keys": ["ctrl+alt+p"], "command": "refact_pause" }, + { "keys": ["primary+option+p"], "command": "refact_pause" } ] From d815328a242fb084fef03e60e3d7769513f67ff6 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Mon, 4 Mar 2024 17:15:26 -0500 Subject: [PATCH 04/12] settings now cause server restart --- __init__.py | 8 +++++++- src/refact_lsp.py | 3 --- src/refact_process.py | 14 ++++++++++---- src/refact_sessions.py | 4 ++++ 4 files changed, 21 insertions(+), 8 deletions(-) diff --git a/__init__.py b/__init__.py index b52d6d6..f0b98d4 100644 --- a/__init__.py +++ b/__init__.py @@ -72,11 +72,18 @@ def on_text_command(self, view, command_name, args): elif command_name == "drag_select": session.clear_completion() +def restart_server(): + global refact_session_manager + print("restarting server") + if refact_session_manager: + refact_session_manager.restart_server() + def plugin_loaded(): global refact_session_manager global start_refact s = sublime.load_settings("refact.sublime-settings") pause_completion = s.get("pause_completion", False) + s.add_on_change("restart_server", restart_server) if pause_completion: sublime.status_message("⏸️ refact.ai") else: @@ -158,4 +165,3 @@ def run(self, edit): class RefactClearCompletion(sublime_plugin.TextCommand): def run(self, edit): refact_session_manager.get_session(self.view).clear_completion() - diff --git a/src/refact_lsp.py b/src/refact_lsp.py index 90ba084..b8b1cde 100644 --- a/src/refact_lsp.py +++ b/src/refact_lsp.py @@ -112,9 +112,6 @@ def shutdown(self): self.statusbar.handle_err(err) print("lsp error shutdown") - - def logMessage(self, args): - print("logMessage", args) def connect(self, process): capabilities = {} diff --git a/src/refact_process.py b/src/refact_process.py index 8b6e02e..57bc20f 100644 --- a/src/refact_process.py +++ b/src/refact_process.py @@ -41,9 +41,13 @@ def get_server_commands(self): def start_server(self): self.active = True server_cmds = self.get_server_commands() - startupinfo = subprocess.STARTUPINFO() - startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW - self.process = subprocess.Popen(server_cmds, startupinfo=startupinfo, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) + + if hasattr(subprocess, 'STARTUPINFO'): + startupinfo = subprocess.STARTUPINFO() + startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW + self.process = subprocess.Popen(server_cmds, startupinfo=startupinfo, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) + else: + self.process = subprocess.Popen(server_cmds, stdin = subprocess.PIPE, stdout = subprocess.PIPE, stderr=subprocess.PIPE, shell=False) self.statusbar.update_statusbar("ok") if not self.connection is None: @@ -52,7 +56,9 @@ def start_server(self): self.connection = LSP(self.process, self.statusbar) def stop_server(self): - self.connection.shutdown() + if not self.connection is None: + self.connection.shutdown() self.process.terminate() + self.active = False self.statusbar.update_statusbar("pause") diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 88c36e8..26aab89 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -19,6 +19,10 @@ def __init__(self): self.connection = self.process.start_server() self.views = {} + def restart_server(self): + self.shutdown() + self.start() + def start(self): self.connection = self.process.start_server() From 534a79236b36d441506f29b803218b813fcde3ea Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Thu, 7 Mar 2024 19:09:02 -0500 Subject: [PATCH 05/12] fixed completion space issues --- refact.sublime-settings | 2 +- src/completion_text.py | 11 ++++++----- src/phantom_state.py | 15 +++++++++++---- src/refact_sessions.py | 10 +++++++--- src/utils.py | 8 ++++++-- 5 files changed, 31 insertions(+), 15 deletions(-) diff --git a/refact.sublime-settings b/refact.sublime-settings index 1bd8669..9a6063e 100644 --- a/refact.sublime-settings +++ b/refact.sublime-settings @@ -9,7 +9,7 @@ "code_completion_model": "", "code_completion_scratchpad": "", "pause_completion": false, - "telemetry_code_snippets": false + "telemetry_basic": true // Use something like // tail -f -n 1000 ~/.cache/refact/logs/rustbinary.2024-02-07 // to see what's going on with the server diff --git a/src/completion_text.py b/src/completion_text.py index 5297b12..f1409fc 100644 --- a/src/completion_text.py +++ b/src/completion_text.py @@ -45,12 +45,13 @@ def collect_space(s, index): def get_completion_text(point, text, line, end = None): if not line or line.isspace(): - s = replace_tab(text) + tab_size = get_tab_size() + + s = replace_tab(text, tab_size) res_space = get_nonwhitespace(s) - l = replace_tab(line) - diff = res_space - len(l) - if diff > 0: - return s[(res_space - diff):] + line_len = len(replace_tab(line, tab_size)) + if res_space > line_len: + return s[line_len:] else: return s[res_space:] diff --git a/src/phantom_state.py b/src/phantom_state.py index a8754c6..7b6a90a 100644 --- a/src/phantom_state.py +++ b/src/phantom_state.py @@ -4,7 +4,7 @@ import sublime_plugin import html from .utils import * -from .completion_text import get_completion_text +from .completion_text import get_completion_text, get_nonwhitespace from dataclasses import dataclass from typing import NamedTuple @@ -107,7 +107,7 @@ def __init__(self, view): self.update_step = False self.phantoms_visible = False s = sublime.load_settings("Preferences.sublime-settings") - self.tab_size = s.get("tab_size", 4) + self.tab_size = get_tab_size() invisibleDiv = """ @@ -176,10 +176,17 @@ def show_start_line_completion(self, position, text): return previous_line = get_previous_line(self.view, position) + previous_line_text = self.view.substr(previous_line) + popup_point = previous_line.a - if len(previous_line) > 0: + if previous_line_text[0] == '\t': + popup_point = previous_line.a + text = " " + text + elif len(previous_line) > 0: popup_point = popup_point + 1 - self.view.show_popup(self.create_annotation_template(text), location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) + + popup_text = self.create_annotation_template(text) + self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) def add_phantoms(self, new_phantoms): view = self.view diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 26aab89..71da71c 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -52,6 +52,7 @@ def get_session(self, view): class RefactSession: def __init__(self, view, connection, is_ui = False): self.completion_in_process = False + self.update_step = False self.session_state = 0 self.version = 0 self.view = view @@ -95,7 +96,7 @@ def update_completion(self): self.clear_completion() return - if self.phantom_state.update_step: + if self.update_step or self.phantom_state.update_step: return if self.has_completion(): @@ -114,9 +115,11 @@ def get_completion(self): return self.current_completion def clear_completion(self): + self.update_step = True self.session_state = self.session_state + 1 - self.current_completion = None self.phantom_state.clear_phantoms() + self.current_completion = None + self.update_step = False def is_paused(self): s = sublime.load_settings("refact.sublime-settings") @@ -198,7 +201,8 @@ def show_completions_inner(self, version, prefix, locations, multiline = False): return text = get_line(self.view, location) - suggestions = [text[:rc[1]] + s['code_completion'] for s in completions] + suggestion_prefix = "" if not prefix or prefix.isspace() else text[:rc[1]] + suggestions = [suggestion_prefix + s['code_completion'] for s in completions] sublime.set_timeout(lambda: self.set_phantoms(version, location, suggestions[0])) def accept_completion(self): diff --git a/src/utils.py b/src/utils.py index 3d10aeb..624cfc5 100644 --- a/src/utils.py +++ b/src/utils.py @@ -37,9 +37,13 @@ def filter_none(l): def identity(x): return x -def replace_tab(text): +def get_tab_size(): s = sublime.load_settings("Preferences.sublime-settings") - tab_size = s.get("tab_size", 4) + return s.get("tab_size", 4) + +def replace_tab(text, tab_size = None): + if tab_size is None: + tab_size = get_tab_size() return text.replace('\t', ' ' * tab_size) From 00fd50d96dbbd9d4aaae1dab6051a4f207a18d62 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Fri, 8 Mar 2024 13:01:27 -0500 Subject: [PATCH 06/12] fixed did open and reports workspace folders --- refact.sublime-settings | 2 +- src/completion_text.py | 11 ++++++----- src/phantom_state.py | 15 +++++++++++---- src/refact_lsp.py | 13 +++++++++---- src/refact_sessions.py | 13 +++++++++---- src/utils.py | 8 ++++++-- 6 files changed, 42 insertions(+), 20 deletions(-) diff --git a/refact.sublime-settings b/refact.sublime-settings index 1bd8669..9a6063e 100644 --- a/refact.sublime-settings +++ b/refact.sublime-settings @@ -9,7 +9,7 @@ "code_completion_model": "", "code_completion_scratchpad": "", "pause_completion": false, - "telemetry_code_snippets": false + "telemetry_basic": true // Use something like // tail -f -n 1000 ~/.cache/refact/logs/rustbinary.2024-02-07 // to see what's going on with the server diff --git a/src/completion_text.py b/src/completion_text.py index 5297b12..f1409fc 100644 --- a/src/completion_text.py +++ b/src/completion_text.py @@ -45,12 +45,13 @@ def collect_space(s, index): def get_completion_text(point, text, line, end = None): if not line or line.isspace(): - s = replace_tab(text) + tab_size = get_tab_size() + + s = replace_tab(text, tab_size) res_space = get_nonwhitespace(s) - l = replace_tab(line) - diff = res_space - len(l) - if diff > 0: - return s[(res_space - diff):] + line_len = len(replace_tab(line, tab_size)) + if res_space > line_len: + return s[line_len:] else: return s[res_space:] diff --git a/src/phantom_state.py b/src/phantom_state.py index a8754c6..7b6a90a 100644 --- a/src/phantom_state.py +++ b/src/phantom_state.py @@ -4,7 +4,7 @@ import sublime_plugin import html from .utils import * -from .completion_text import get_completion_text +from .completion_text import get_completion_text, get_nonwhitespace from dataclasses import dataclass from typing import NamedTuple @@ -107,7 +107,7 @@ def __init__(self, view): self.update_step = False self.phantoms_visible = False s = sublime.load_settings("Preferences.sublime-settings") - self.tab_size = s.get("tab_size", 4) + self.tab_size = get_tab_size() invisibleDiv = """ @@ -176,10 +176,17 @@ def show_start_line_completion(self, position, text): return previous_line = get_previous_line(self.view, position) + previous_line_text = self.view.substr(previous_line) + popup_point = previous_line.a - if len(previous_line) > 0: + if previous_line_text[0] == '\t': + popup_point = previous_line.a + text = " " + text + elif len(previous_line) > 0: popup_point = popup_point + 1 - self.view.show_popup(self.create_annotation_template(text), location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) + + popup_text = self.create_annotation_template(text) + self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) def add_phantoms(self, new_phantoms): view = self.view diff --git a/src/refact_lsp.py b/src/refact_lsp.py index b8b1cde..e74c1c8 100644 --- a/src/refact_lsp.py +++ b/src/refact_lsp.py @@ -1,6 +1,8 @@ +import sublime import os import socket import pathlib +import traceback from typing import Optional, Dict, Tuple from .pylspclient.lsp_structs import * from .pylspclient.lsp_endpoint import LspEndpoint @@ -12,9 +14,9 @@ def __init__(self, process, statusbar): self.statusbar = statusbar self.connect(process) - def load_document(self, file_name: str, text: str, version: int = 1, languageId = LANGUAGE_IDENTIFIER.PYTHON): + def load_document(self, file_name: str, version: int, text: str, languageId = LANGUAGE_IDENTIFIER.PYTHON): print("load_document", file_name) - + if languageId is None: languageId = LANGUAGE_IDENTIFIER.PYTHON @@ -118,9 +120,12 @@ def connect(self, process): json_rpc_endpoint = JsonRpcEndpoint(process.stdin, process.stdout) self.lsp_endpoint = LspEndpoint(json_rpc_endpoint, notify_callbacks = {"window/logMessage":print}) self.lsp_client = LspClient(self.lsp_endpoint) - + windows = sublime.windows() + workspaces = [{'name': folder, 'uri': pathlib.Path(folder).as_uri()} for w in windows for folder in w.folders()] + + print("workspaces: ", workspaces) try: - self.lsp_client.initialize(process.pid, None, None, None, capabilities, "off", None) + self.lsp_client.initialize(process.pid, None, None, None, capabilities, "off", workspaces) except Exception as err: self.statusbar.handle_err(err) print("lsp initialize error", err) diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 26aab89..9757113 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -52,6 +52,7 @@ def get_session(self, view): class RefactSession: def __init__(self, view, connection, is_ui = False): self.completion_in_process = False + self.update_step = False self.session_state = 0 self.version = 0 self.view = view @@ -69,11 +70,12 @@ def __init__(self, view, connection, is_ui = False): syntax = view.scope_name(get_cursor_point(view)) file_type = syntax[(syntax.rindex(".") + 1):].strip() self.languageId = get_language_id(file_type) - self.connection().load_document(self.file_name, get_text(self.view), self.languageId) + self.connection().load_document(self.file_name, version = self.version, text = get_text(self.view), languageId = self.languageId) def notify_document_update(self): if self.is_ui or self.phantom_state.update_step: return + self.version = self.version + 1 self.connection().did_change(self.file_name, self.version, get_text(self.view), self.languageId) def notify_close(self): @@ -95,7 +97,7 @@ def update_completion(self): self.clear_completion() return - if self.phantom_state.update_step: + if self.update_step or self.phantom_state.update_step: return if self.has_completion(): @@ -114,9 +116,11 @@ def get_completion(self): return self.current_completion def clear_completion(self): + self.update_step = True self.session_state = self.session_state + 1 - self.current_completion = None self.phantom_state.clear_phantoms() + self.current_completion = None + self.update_step = False def is_paused(self): s = sublime.load_settings("refact.sublime-settings") @@ -198,7 +202,8 @@ def show_completions_inner(self, version, prefix, locations, multiline = False): return text = get_line(self.view, location) - suggestions = [text[:rc[1]] + s['code_completion'] for s in completions] + suggestion_prefix = "" if not prefix or prefix.isspace() else text[:rc[1]] + suggestions = [suggestion_prefix + s['code_completion'] for s in completions] sublime.set_timeout(lambda: self.set_phantoms(version, location, suggestions[0])) def accept_completion(self): diff --git a/src/utils.py b/src/utils.py index 3d10aeb..624cfc5 100644 --- a/src/utils.py +++ b/src/utils.py @@ -37,9 +37,13 @@ def filter_none(l): def identity(x): return x -def replace_tab(text): +def get_tab_size(): s = sublime.load_settings("Preferences.sublime-settings") - tab_size = s.get("tab_size", 4) + return s.get("tab_size", 4) + +def replace_tab(text, tab_size = None): + if tab_size is None: + tab_size = get_tab_size() return text.replace('\t', ' ' * tab_size) From 2eb0debe220e037b2ace369eb35c341978b0b4b7 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Mon, 11 Mar 2024 17:55:41 -0400 Subject: [PATCH 07/12] fixed pause issues and completion timing bug --- __init__.py | 14 +++++++++----- src/refact_sessions.py | 24 ++++++++---------------- 2 files changed, 17 insertions(+), 21 deletions(-) diff --git a/__init__.py b/__init__.py index f0b98d4..6563e17 100644 --- a/__init__.py +++ b/__init__.py @@ -40,7 +40,7 @@ def on_query_context(self, view, key, operator, operand, match_all): if start_refact: if key == "refact.show_completion": return refact_session_manager.get_session(view).completion_visible() - + def on_post_text_command(self, view, command_name, args): if start_refact: session = refact_session_manager.get_session(view) @@ -74,9 +74,13 @@ def on_text_command(self, view, command_name, args): def restart_server(): global refact_session_manager - print("restarting server") + if refact_session_manager: - refact_session_manager.restart_server() + s = sublime.load_settings("refact.sublime-settings") + pause_completion = s.get("pause_completion", False) + + if not pause_completion: + refact_session_manager.restart_server() def plugin_loaded(): global refact_session_manager @@ -149,14 +153,14 @@ def run(self, edit): class RefactPause(sublime_plugin.TextCommand): def run(self, edit): global start_refact - start_refact= False s = sublime.load_settings("refact.sublime-settings") pause_status = s.get("pause_completion", False) pause_status = not pause_status + start_refact = not pause_status s.set("pause_completion", pause_status) sublime.save_settings("refact.sublime-settings") - if not pause_status: + if not pause_status and refact_session_manager is None: refact_start() else: if refact_session_manager: diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 9757113..d23203c 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -51,7 +51,6 @@ def get_session(self, view): class RefactSession: def __init__(self, view, connection, is_ui = False): - self.completion_in_process = False self.update_step = False self.session_state = 0 self.version = 0 @@ -75,6 +74,7 @@ def __init__(self, view, connection, is_ui = False): def notify_document_update(self): if self.is_ui or self.phantom_state.update_step: return + self.session_state = self.session_state + 1 self.version = self.version + 1 self.connection().did_change(self.file_name, self.version, get_text(self.view), self.languageId) @@ -102,7 +102,8 @@ def update_completion(self): if self.has_completion(): self.phantom_state.update() - if not self.completion_visible() and not self.completion_in_process: + + if not self.completion_visible(): text = get_cursor_line(self.view) self.show_completions(text, [get_cursor_point(self.view)], len(text) == 0 or text.isspace()) @@ -126,17 +127,12 @@ def is_paused(self): s = sublime.load_settings("refact.sublime-settings") return s.get("pause_completion") - def clear_completion_process(self): - self.completion_in_process = False - def show_completions(self, prefix, locations, multiline = False): - if not self.phantom_state.update_step and not self.completion_in_process: - self.completion_in_process = True + if not self.phantom_state.update_step: sublime.set_timeout_async(lambda:self.show_completions_inner(self.session_state, prefix, locations, multiline)) def set_phantoms(self, version, location, completion): if self.session_state != version or not self.is_position_valid(location): - self.clear_completion_process() return text = get_line(self.view, location) @@ -150,8 +146,8 @@ def set_phantoms(self, version, location, completion): self.phantom_state.set_new_phantoms([[PhantomInsertion(location, insertions[0]), PhantomInsertion(len(remainder), next_text)]]) else: self.current_completion = completion + self.phantom_state.set_new_phantoms([[PhantomInsertion(location, completion)]]) - self.clear_completion_process() def is_position_valid(self, location): rc = self.view.rowcol(location) @@ -164,21 +160,18 @@ def is_position_valid(self, location): return True def show_completions_inner(self, version, prefix, locations, multiline = False): + if version != self.session_state: - self.clear_completion_process() return if self.is_ui or self.phantom_state.update_step: - self.clear_completion_process() return if self.is_paused(): - self.clear_completion_process() return location = locations[0] if not self.is_position_valid(location): - self.clear_completion_process() return rc = self.view.rowcol(location) @@ -187,10 +180,10 @@ def show_completions_inner(self, version, prefix, locations, multiline = False): pos_arg = (rc[0], 0) else: pos_arg = rc + res = self.connection().get_completions(self.file_name, pos_arg, multiline) if res is None: - self.clear_completion_process() return completions = res["choices"] @@ -198,8 +191,7 @@ def show_completions_inner(self, version, prefix, locations, multiline = False): if len(completions) > 0: completion = completions[0]['code_completion'] if not completion or len(completion) == 0 or completion.isspace(): - self.clear_completion_process() - return + return text = get_line(self.view, location) suggestion_prefix = "" if not prefix or prefix.isspace() else text[:rc[1]] From 2369a80d64d916847c414087b2ad0aa22f2a4bd3 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Thu, 21 Mar 2024 20:03:32 -0400 Subject: [PATCH 08/12] changing popup settings to fix minor bugs --- src/phantom_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phantom_state.py b/src/phantom_state.py index 7b6a90a..94875f7 100644 --- a/src/phantom_state.py +++ b/src/phantom_state.py @@ -186,7 +186,7 @@ def show_start_line_completion(self, position, text): popup_point = popup_point + 1 popup_text = self.create_annotation_template(text) - self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) + self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT | sublime.HIDE_ON_MOUSE_MOVE, max_width = 999) def add_phantoms(self, new_phantoms): view = self.view From 1eb848557c022d5b40e4c3e372caf7f5cee3b513 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Thu, 21 Mar 2024 22:03:20 -0400 Subject: [PATCH 09/12] fixed lingering pause bugs --- __init__.py | 8 ++++++-- src/refact_lsp.py | 5 +++-- src/refact_process.py | 4 ++++ src/refact_sessions.py | 13 ++++++++++--- src/statusbar.py | 5 ++++- 5 files changed, 27 insertions(+), 8 deletions(-) diff --git a/__init__.py b/__init__.py index 6563e17..ed4c03c 100644 --- a/__init__.py +++ b/__init__.py @@ -21,7 +21,7 @@ def on_modified(self, view): session = refact_session_manager.get_session(view) session.notify_document_update() session.update_completion() - + def on_close(self, view): if not start_refact: return @@ -93,13 +93,17 @@ def plugin_loaded(): else: refact_start() +def get_start_refact(): + print("get_start_refact", start_refact) + return start_refact + def refact_start(): global refact_session_manager global start_refact if refact_session_manager: refact_session_manager.start() else: - refact_session_manager = RefactSessionManager() + refact_session_manager = RefactSessionManager(get_start_refact) start_refact= True class RefactStartCommand(sublime_plugin.TextCommand): diff --git a/src/refact_lsp.py b/src/refact_lsp.py index e74c1c8..9686df8 100644 --- a/src/refact_lsp.py +++ b/src/refact_lsp.py @@ -16,7 +16,7 @@ def __init__(self, process, statusbar): def load_document(self, file_name: str, version: int, text: str, languageId = LANGUAGE_IDENTIFIER.PYTHON): print("load_document", file_name) - + if languageId is None: languageId = LANGUAGE_IDENTIFIER.PYTHON @@ -106,12 +106,13 @@ def get_completions(self, file_name, pos: Tuple[int, int], multiline: bool = Fal return res except Exception as err: self.statusbar.handle_err(err) + return + def shutdown(self): try: self.lsp_client.shutdown() except Exception as err: - self.statusbar.handle_err(err) print("lsp error shutdown") diff --git a/src/refact_process.py b/src/refact_process.py index 57bc20f..3bef189 100644 --- a/src/refact_process.py +++ b/src/refact_process.py @@ -10,6 +10,7 @@ class RefactProcessWrapper(): def __init__(self): self.connection = None self.active = False + self.process = None self.statusbar = StatusBar() def get_server_path(self): @@ -42,6 +43,9 @@ def start_server(self): self.active = True server_cmds = self.get_server_commands() + if not self.process is None: + self.process.kill() + if hasattr(subprocess, 'STARTUPINFO'): startupinfo = subprocess.STARTUPINFO() startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW diff --git a/src/refact_sessions.py b/src/refact_sessions.py index d23203c..8ec4b55 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -11,9 +11,12 @@ from .phantom_state import PhantomState, PhantomInsertion from .completion_text import get_nonwhitespace +dummyConnection = {"load_document":identity, "did_change" : identity, "did_close" : identity, "did_save" : identity, "get_completions":identity} + class RefactSessionManager: - def __init__(self): + def __init__(self, is_active): + self.is_active = is_active self.connection = None self.process = RefactProcessWrapper() self.connection = self.process.start_server() @@ -25,7 +28,9 @@ def restart_server(self): def start(self): self.connection = self.process.start_server() - + for key, session in self.views.items(): + session.notify_document_update() + def shutdown(self): if self.process and self.process.active: self.process.stop_server() @@ -39,7 +44,9 @@ def get_view_id(self, view): return "UI" def get_connection(self): - if not self.process.active: + if not self.is_active(): + return dummyConnection + if not self.process.active: self.process.start_server() return self.process.connection diff --git a/src/statusbar.py b/src/statusbar.py index e911d87..bf9104d 100644 --- a/src/statusbar.py +++ b/src/statusbar.py @@ -1,4 +1,3 @@ - import sublime class StatusBar: @@ -28,12 +27,16 @@ def status_loop(self): sublime.set_timeout(self.status_loop, 100) def update_statusbar(self, status, msg = ""): + print("update_statusbar", status, msg) self.status = status self.msg = msg self.duration = 5 self.status_loop() def handle_err(self, err): + if self.status == "pause": + return + if not isinstance(err, str): if hasattr(err, 'message'): err = err.message From 502ceb504e510822810163154552c703f3f76da1 Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Fri, 22 Mar 2024 13:28:34 -0400 Subject: [PATCH 10/12] fix small bug with get completions and dummyConnection --- src/refact_sessions.py | 2 +- src/utils.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/refact_sessions.py b/src/refact_sessions.py index 8ec4b55..d3a1438 100644 --- a/src/refact_sessions.py +++ b/src/refact_sessions.py @@ -11,7 +11,7 @@ from .phantom_state import PhantomState, PhantomInsertion from .completion_text import get_nonwhitespace -dummyConnection = {"load_document":identity, "did_change" : identity, "did_close" : identity, "did_save" : identity, "get_completions":identity} +dummyConnection = {"load_document":identity, "did_change" : identity, "did_close" : identity, "did_save" : identity, "get_completions":noop} class RefactSessionManager: diff --git a/src/utils.py b/src/utils.py index 624cfc5..b7bcd1c 100644 --- a/src/utils.py +++ b/src/utils.py @@ -37,6 +37,9 @@ def filter_none(l): def identity(x): return x +def noop(): + return None + def get_tab_size(): s = sublime.load_settings("Preferences.sublime-settings") return s.get("tab_size", 4) From 7cd2aa7ab5f9e4774f05733c0b4a09e00aac9a3b Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Wed, 3 Apr 2024 10:36:55 -0400 Subject: [PATCH 11/12] Update phantom_state.py fixed popup bug --- src/phantom_state.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/phantom_state.py b/src/phantom_state.py index 94875f7..7b6a90a 100644 --- a/src/phantom_state.py +++ b/src/phantom_state.py @@ -186,7 +186,7 @@ def show_start_line_completion(self, position, text): popup_point = popup_point + 1 popup_text = self.create_annotation_template(text) - self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT | sublime.HIDE_ON_MOUSE_MOVE, max_width = 999) + self.view.show_popup(popup_text, location = popup_point, flags = sublime.PopupFlags.HIDE_ON_CHARACTER_EVENT, max_width = 999) def add_phantoms(self, new_phantoms): view = self.view From 877a60920307f34e6052647183d2c5fa66fcbe9f Mon Sep 17 00:00:00 2001 From: James Brownlee Date: Wed, 10 Apr 2024 12:49:34 -0400 Subject: [PATCH 12/12] fixed server worspace folder functionality --- __init__.py | 16 ++++++++++++++++ src/statusbar.py | 1 - 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/__init__.py b/__init__.py index ed4c03c..367ce15 100644 --- a/__init__.py +++ b/__init__.py @@ -8,12 +8,16 @@ start_refact = False refact_session_manager = None +open_folders = {} class RefactAutocomplete(sublime_plugin.EventListener): def on_query_completions(self, view, prefix, locations): if start_refact: refact_session_manager.get_session(view).show_completions(prefix, locations) + def on_new_window(self, window): + sublime.set_timeout(lambda: restart_on_new_folder(window), 100) + def on_modified(self, view): if not start_refact: return @@ -85,6 +89,9 @@ def restart_server(): def plugin_loaded(): global refact_session_manager global start_refact + global open_folders + windows = sublime.windows() + open_folders = {folder for w in windows for folder in w.folders()} s = sublime.load_settings("refact.sublime-settings") pause_completion = s.get("pause_completion", False) s.add_on_change("restart_server", restart_server) @@ -93,6 +100,15 @@ def plugin_loaded(): else: refact_start() +def restart_on_new_folder(window): + global open_folders + + window_folders = set(window.folders()) + new_folders = window_folders - open_folders + if len(new_folders) > 0: + open_folders |= new_folders + restart_server() + def get_start_refact(): print("get_start_refact", start_refact) return start_refact diff --git a/src/statusbar.py b/src/statusbar.py index bf9104d..24c959b 100644 --- a/src/statusbar.py +++ b/src/statusbar.py @@ -27,7 +27,6 @@ def status_loop(self): sublime.set_timeout(self.status_loop, 100) def update_statusbar(self, status, msg = ""): - print("update_statusbar", status, msg) self.status = status self.msg = msg self.duration = 5