From 5d89825beceb9f71123b42951393b8d7ec8c7acf Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Sun, 17 May 2026 23:21:00 +0200 Subject: [PATCH 01/10] Fix on_sheet_opened called twice from uri_handler --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 8dce83f1f..662e0283a 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1476,7 +1476,7 @@ def try_open_uri_async( if isinstance(self._plugin, LspPlugin): scheme, _ = parse_uri(uri) if handler := self._plugin.get_uri_handler(scheme): - return handler(uri, flags).then(lambda sheet: self._on_sheet_opened(sheet, uri, r)) + return handler(uri, flags).then(lambda sheet: sheet.view() if sheet else None) else: return self._open_uri_with_plugin_async(self._plugin, uri, r, flags, group) return None From afb397878bfae117b174ea76db19a1f622778c98 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 21:24:48 +0200 Subject: [PATCH 02/10] Revert "Fix on_sheet_opened called twice from uri_handler" This reverts commit 5d89825beceb9f71123b42951393b8d7ec8c7acf. --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 662e0283a..8dce83f1f 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1476,7 +1476,7 @@ def try_open_uri_async( if isinstance(self._plugin, LspPlugin): scheme, _ = parse_uri(uri) if handler := self._plugin.get_uri_handler(scheme): - return handler(uri, flags).then(lambda sheet: sheet.view() if sheet else None) + return handler(uri, flags).then(lambda sheet: self._on_sheet_opened(sheet, uri, r)) else: return self._open_uri_with_plugin_async(self._plugin, uri, r, flags, group) return None From d415e8c6cca39489b21de8c474490167f7d0935e Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 21:28:40 +0200 Subject: [PATCH 03/10] update docs --- docs/src/migrating_to_lsp_plugin.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/src/migrating_to_lsp_plugin.md b/docs/src/migrating_to_lsp_plugin.md index b89343e24..4a335a78b 100644 --- a/docs/src/migrating_to_lsp_plugin.md +++ b/docs/src/migrating_to_lsp_plugin.md @@ -435,7 +435,7 @@ from LSP.plugin import uri_handler def on_open_foo_uri(self, uri: DocumentUri, flags: sublime.NewFileFlags) -> Promise[sublime.Sheet | None]: title, content, syntax = render_foo_uri(uri) if session := self.weaksession(): - return session.open_scratch_buffer(title, content, syntax, uri, None, flags) + return session.open_scratch_buffer(title, content, syntax, uri, None, flags).then(_: None) return Promise.resolve(None) ``` From 85043ec5662e9b48b7d9729e98abaa7407e86fb7 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 21:36:50 +0200 Subject: [PATCH 04/10] remove fragment from lsp_uri --- plugin/core/sessions.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 8dce83f1f..c5cad959d 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -172,6 +172,7 @@ from typing import Union from typing_extensions import TypeAlias from typing_extensions import TypeGuard +from urllib.parse import urldefrag from weakref import WeakSet import itertools import mdpopups @@ -1578,7 +1579,8 @@ def _on_sheet_opened( self, sheet: sublime.Sheet | None, uri: DocumentUri, r: Range | None ) -> Promise[sublime.View | None]: if sheet and (view := sheet.view()): - view.settings().set('lsp_uri', uri) # Preserve original URI given by the language server + uri_no_fragment = urldefrag(uri).url + view.settings().set('lsp_uri', uri_no_fragment) if r: center_selection(view, r) return Promise.resolve(view) From d4a4b60e4a372512e6f049969bf159a9bbd35d8b Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 21:45:02 +0200 Subject: [PATCH 05/10] require title --- plugin/core/sessions.py | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index c5cad959d..5cacbaa02 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1535,9 +1535,9 @@ def _open_uri_with_plugin_async( group: int, ) -> Promise[sublime.View | None] | None: # I cannot type-hint an unpacked tuple - pair: PackagedTask[tuple[str | None, str, str]] = Promise.packaged_task() + pair: PackagedTask[tuple[str, str, str]] = Promise.packaged_task() # It'd be nice to have automatic tuple unpacking continuations - callback = lambda a, b, c: pair[1]((a, b, c)) # noqa: E731 + callback = lambda a, b, c: pair[1]((a or 'Untitled', b, c)) # noqa: E731 if plugin.on_open_uri_async(uri, callback): result: PackagedTask[sublime.View | None] = Promise.packaged_task() pair[0].then(lambda tup: self.open_scratch_buffer(*tup, uri, r, flags, group)).then(result[1]) @@ -1546,21 +1546,18 @@ def _open_uri_with_plugin_async( def open_scratch_buffer( self, - title: str | None, + title: str, content: str, syntax: str, uri: DocumentUri, r: Range | None, flags: sublime.NewFileFlags = sublime.NewFileFlags.NONE, group: int = -1, - ) -> Promise[sublime.View | None]: - task: PackagedTask[sublime.View | None] = Promise.packaged_task() + ) -> Promise[sublime.View]: + task: PackagedTask[sublime.View] = Promise.packaged_task() promise, resolve = task def continue_on_main_thread() -> None: - if title is None: - resolve(None) - return if group > -1: self.window.focus_group(group) view = self.window.new_file(syntax=syntax, flags=flags) @@ -1570,7 +1567,7 @@ def continue_on_main_thread() -> None: view.set_name(title) view.run_command("append", {"characters": content}) view.set_read_only(True) - self._on_sheet_opened(view.sheet(), uri, r).then(resolve) + self._on_sheet_opened(view.sheet(), uri, r).then(lambda _: resolve(view)) sublime.set_timeout(continue_on_main_thread) return promise From d5551a2a600755e68554bc0529d922dc14720229 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 21:57:43 +0200 Subject: [PATCH 06/10] _on_sheet_opened doesn't need to use promise --- plugin/core/sessions.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 5cacbaa02..ccfa1d26c 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1567,21 +1567,20 @@ def continue_on_main_thread() -> None: view.set_name(title) view.run_command("append", {"characters": content}) view.set_read_only(True) - self._on_sheet_opened(view.sheet(), uri, r).then(lambda _: resolve(view)) + self._on_sheet_opened(view.sheet(), uri, r) + resolve(view) sublime.set_timeout(continue_on_main_thread) return promise - def _on_sheet_opened( - self, sheet: sublime.Sheet | None, uri: DocumentUri, r: Range | None - ) -> Promise[sublime.View | None]: + def _on_sheet_opened(self, sheet: sublime.Sheet | None, uri: DocumentUri, r: Range | None) -> sublime.View | None: if sheet and (view := sheet.view()): uri_no_fragment = urldefrag(uri).url view.settings().set('lsp_uri', uri_no_fragment) if r: center_selection(view, r) - return Promise.resolve(view) - return Promise.resolve(None) + return view + return None def open_location_async( self, From 0bee883267af00c181a98a0e168dd5a1dc24ca0b Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Mon, 18 May 2026 22:05:15 +0200 Subject: [PATCH 07/10] make uri optional --- plugin/core/sessions.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index ccfa1d26c..687f3c676 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1549,8 +1549,8 @@ def open_scratch_buffer( title: str, content: str, syntax: str, - uri: DocumentUri, - r: Range | None, + uri: DocumentUri | None = None, + r: Range | None = None, flags: sublime.NewFileFlags = sublime.NewFileFlags.NONE, group: int = -1, ) -> Promise[sublime.View]: @@ -1573,10 +1573,13 @@ def continue_on_main_thread() -> None: sublime.set_timeout(continue_on_main_thread) return promise - def _on_sheet_opened(self, sheet: sublime.Sheet | None, uri: DocumentUri, r: Range | None) -> sublime.View | None: + def _on_sheet_opened( + self, sheet: sublime.Sheet | None, uri: DocumentUri | None, r: Range | None + ) -> sublime.View | None: if sheet and (view := sheet.view()): - uri_no_fragment = urldefrag(uri).url - view.settings().set('lsp_uri', uri_no_fragment) + if uri: + uri_no_fragment = urldefrag(uri).url + view.settings().set('lsp_uri', uri_no_fragment) if r: center_selection(view, r) return view From f8dac33665e4c8e05b814adf0529f03413897386 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Tue, 19 May 2026 07:21:04 +0200 Subject: [PATCH 08/10] untitled --- plugin/core/sessions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index c215ce403..20e294c0a 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1523,7 +1523,7 @@ def _open_uri_with_plugin_async( # I cannot type-hint an unpacked tuple pair: PackagedTask[tuple[str, str, str]] = Promise.packaged_task() # It'd be nice to have automatic tuple unpacking continuations - callback = lambda a, b, c: pair[1]((a or 'Untitled', b, c)) # noqa: E731 + callback = lambda a, b, c: pair[1]((a or 'untitled', b, c)) # noqa: E731 if plugin.on_open_uri_async(uri, callback): result: PackagedTask[sublime.View | None] = Promise.packaged_task() pair[0].then(lambda tup: self.open_scratch_buffer(*tup, uri, r, flags, group)).then(result[1]) From dbab2e0a29786881bc212fa2b363114c0fbd0f70 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Tue, 19 May 2026 19:04:38 +0200 Subject: [PATCH 09/10] address --- docs/src/migrating_to_lsp_plugin.md | 2 +- plugin/core/sessions.py | 20 +++++++------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/docs/src/migrating_to_lsp_plugin.md b/docs/src/migrating_to_lsp_plugin.md index 4a335a78b..a6b101e0f 100644 --- a/docs/src/migrating_to_lsp_plugin.md +++ b/docs/src/migrating_to_lsp_plugin.md @@ -435,7 +435,7 @@ from LSP.plugin import uri_handler def on_open_foo_uri(self, uri: DocumentUri, flags: sublime.NewFileFlags) -> Promise[sublime.Sheet | None]: title, content, syntax = render_foo_uri(uri) if session := self.weaksession(): - return session.open_scratch_buffer(title, content, syntax, uri, None, flags).then(_: None) + return session.open_scratch_buffer(title, content, syntax, flags).then(lambda view: view.sheet()) return Promise.resolve(None) ``` diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 20e294c0a..926032f77 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1522,12 +1522,12 @@ def _open_uri_with_plugin_async( ) -> Promise[sublime.View | None] | None: # I cannot type-hint an unpacked tuple pair: PackagedTask[tuple[str, str, str]] = Promise.packaged_task() + promise, resolve = pair # It'd be nice to have automatic tuple unpacking continuations - callback = lambda a, b, c: pair[1]((a or 'untitled', b, c)) # noqa: E731 + callback = lambda a, b, c: resolve((a or 'untitled', b, c)) # noqa: E731 if plugin.on_open_uri_async(uri, callback): - result: PackagedTask[sublime.View | None] = Promise.packaged_task() - pair[0].then(lambda tup: self.open_scratch_buffer(*tup, uri, r, flags, group)).then(result[1]) - return result[0] + return promise.then(lambda tup: self.open_scratch_buffer(*tup, flags, group)) \ + .then(lambda view: self._on_sheet_opened(view.sheet(), uri, r)) return None def open_scratch_buffer( @@ -1535,8 +1535,6 @@ def open_scratch_buffer( title: str, content: str, syntax: str, - uri: DocumentUri | None = None, - r: Range | None = None, flags: sublime.NewFileFlags = sublime.NewFileFlags.NONE, group: int = -1, ) -> Promise[sublime.View]: @@ -1553,19 +1551,15 @@ def continue_on_main_thread() -> None: view.set_name(title) view.run_command("append", {"characters": content}) view.set_read_only(True) - self._on_sheet_opened(view.sheet(), uri, r) resolve(view) sublime.set_timeout(continue_on_main_thread) return promise - def _on_sheet_opened( - self, sheet: sublime.Sheet | None, uri: DocumentUri | None, r: Range | None - ) -> sublime.View | None: + def _on_sheet_opened(self, sheet: sublime.Sheet | None, uri: DocumentUri, r: Range | None) -> sublime.View | None: if sheet and (view := sheet.view()): - if uri: - uri_no_fragment = urldefrag(uri).url - view.settings().set('lsp_uri', uri_no_fragment) + uri_no_fragment = urldefrag(uri).url + view.settings().set('lsp_uri', uri_no_fragment) if r: center_selection(view, r) return view From 30492aec905e35b6d38ddba44b8ab77804f67c14 Mon Sep 17 00:00:00 2001 From: Rafal Chlodnicki Date: Tue, 19 May 2026 19:11:11 +0200 Subject: [PATCH 10/10] resolve --- plugin/core/sessions.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugin/core/sessions.py b/plugin/core/sessions.py index 926032f77..f1c3a8f86 100644 --- a/plugin/core/sessions.py +++ b/plugin/core/sessions.py @@ -1528,6 +1528,8 @@ def _open_uri_with_plugin_async( if plugin.on_open_uri_async(uri, callback): return promise.then(lambda tup: self.open_scratch_buffer(*tup, flags, group)) \ .then(lambda view: self._on_sheet_opened(view.sheet(), uri, r)) + # resolve unused promise + resolve(('', '', '')) return None def open_scratch_buffer(