We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
LSP Document Symbols downside compared to native one
**Describe the bug**
I've been running with `cmd+r` overridden to use Document Symbols from LSP. The functionality is better than native but it has one downside compared to native behavior. Namely, with native, I can trigger the shortcut and start typing immediately. The quick panel appears immediately (synchronously or at least with almost no latency). When using LSP's document symbol, the quick panel only opens after we receive server response so, being used to just start typing my query right away, my query ends up being inserted into the active view instead.

Ideally, the quick panel would open right away, even before the response comes, but I guess the API might not let us do that.

Alternatively, we could potentially work around that somehow by capturing user input when the command is triggered and before the quick panel is shown.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `plugin/symbols.py`
Content:
```
1 from .core.protocol import Request, Range
2 from .core.registry import LspTextCommand
3 from .core.typing import Any, List, Optional, Tuple, Dict, Generator
4 from .core.views import location_to_encoded_filename
5 from .core.views import range_to_region
6 from .core.views import SYMBOL_KINDS
7 from .core.views import text_document_identifier
8 from contextlib import contextmanager
9 import os
10 import sublime
11 import sublime_plugin
12 
13 
14 def unpack_lsp_kind(kind: int) -> Tuple[int, str, str, str]:
15     if 1 <= kind <= len(SYMBOL_KINDS):
16         return SYMBOL_KINDS[kind - 1]
17     return sublime.KIND_ID_AMBIGUOUS, "?", "???", "comment"
18 
19 
20 def format_symbol_kind(kind: int) -> str:
21     if 1 <= kind <= len(SYMBOL_KINDS):
22         return SYMBOL_KINDS[kind - 1][2]
23     return str(kind)
24 
25 
26 def get_symbol_scope_from_lsp_kind(kind: int) -> str:
27     if 1 <= kind <= len(SYMBOL_KINDS):
28         return SYMBOL_KINDS[kind - 1][3]
29     return 'comment'
30 
31 
32 @contextmanager
33 def _additional_name(names: List[str], name: str) -> Generator[None, None, None]:
34     names.append(name)
35     yield
36     names.pop(-1)
37 
38 
39 class LspSelectionClearCommand(sublime_plugin.TextCommand):
40     """
41     Selections may not be modified outside the run method of a text command. Thus, to allow modification in an async
42     context we need to have dedicated commands for this.
43 
44     https://github.com/sublimehq/sublime_text/issues/485#issuecomment-337480388
45     """
46 
47     def run(self, _: sublime.Edit) -> None:
48         self.view.sel().clear()
49 
50 
51 class LspSelectionAddCommand(sublime_plugin.TextCommand):
52 
53     def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:
54         for region in regions:
55             self.view.sel().add(sublime.Region(*region))
56 
57 
58 class LspSelectionSetCommand(sublime_plugin.TextCommand):
59 
60     def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:
61         self.view.sel().clear()
62         for region in regions:
63             self.view.sel().add(sublime.Region(*region))
64 
65 
66 class LspDocumentSymbolsCommand(LspTextCommand):
67 
68     capability = 'documentSymbolProvider'
69     REGIONS_KEY = 'lsp_document_symbols'
70 
71     def __init__(self, view: sublime.View) -> None:
72         super().__init__(view)
73         self.old_regions = []  # type: List[sublime.Region]
74         self.regions = []  # type: List[Tuple[sublime.Region, Optional[sublime.Region], str]]
75         self.is_first_selection = False
76 
77     def run(self, edit: sublime.Edit) -> None:
78         session = self.best_session(self.capability)
79         if session:
80             session.send_request(
81                 Request.documentSymbols({"textDocument": text_document_identifier(self.view)}), self.handle_response)
82 
83     def handle_response(self, response: Any) -> None:
84         window = self.view.window()
85         if window and isinstance(response, list) and len(response) > 0:
86             self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]
87             self.is_first_selection = True
88             window.show_quick_panel(
89                 self.process_symbols(response),
90                 self.on_symbol_selected,
91                 sublime.KEEP_OPEN_ON_FOCUS_LOST,
92                 0,
93                 self.on_highlighted)
94             self.view.run_command("lsp_selection_clear")
95 
96     def region(self, index: int) -> sublime.Region:
97         return self.regions[index][0]
98 
99     def selection_region(self, index: int) -> Optional[sublime.Region]:
100         return self.regions[index][1]
101 
102     def scope(self, index: int) -> str:
103         return self.regions[index][2]
104 
105     def on_symbol_selected(self, index: int) -> None:
106         if index == -1:
107             if len(self.old_regions) > 0:
108                 self.view.run_command("lsp_selection_add", {"regions": [(r.a, r.b) for r in self.old_regions]})
109                 self.view.show_at_center(self.old_regions[0].begin())
110         else:
111             region = self.selection_region(index) or self.region(index)
112             self.view.run_command("lsp_selection_add", {"regions": [(region.a, region.a)]})
113             self.view.show_at_center(region.a)
114         self.view.erase_regions(self.REGIONS_KEY)
115         self.old_regions.clear()
116         self.regions.clear()
117 
118     def on_highlighted(self, index: int) -> None:
119         if self.is_first_selection:
120             self.is_first_selection = False
121             return
122         region = self.region(index)
123         self.view.show_at_center(region.a)
124         self.view.add_regions(self.REGIONS_KEY, [region], self.scope(index), '', sublime.DRAW_NO_FILL)
125 
126     def process_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:
127         self.regions.clear()
128         panel_items = []
129         if 'selectionRange' in items[0]:
130             panel_items = self.process_document_symbols(items)
131         else:
132             panel_items = self.process_symbol_informations(items)
133         # Sort both lists in sync according to the range's begin point.
134         sorted_results = zip(*sorted(zip(self.regions, panel_items), key=lambda item: item[0][0].begin()))
135         sorted_regions, sorted_panel_items = sorted_results
136         self.regions = list(sorted_regions)
137         return list(sorted_panel_items)
138 
139     def process_document_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:
140         quick_panel_items = []  # type: List[sublime.QuickPanelItem]
141         names = []  # type: List[str]
142         for item in items:
143             self.process_document_symbol_recursive(quick_panel_items, item, names)
144         return quick_panel_items
145 
146     def process_document_symbol_recursive(self, quick_panel_items: List[sublime.QuickPanelItem], item: Dict[str, Any],
147                                           names: List[str]) -> None:
148         lsp_kind = item["kind"]
149         self.regions.append((range_to_region(Range.from_lsp(item['range']), self.view),
150                              range_to_region(Range.from_lsp(item['selectionRange']), self.view),
151                              get_symbol_scope_from_lsp_kind(lsp_kind)))
152         name = item['name']
153         with _additional_name(names, name):
154             st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)
155             formatted_names = " > ".join(names)
156             st_details = item.get("detail") or ""
157             if st_details:
158                 st_details = "{} | {}".format(st_details, formatted_names)
159             else:
160                 st_details = formatted_names
161             quick_panel_items.append(
162                 sublime.QuickPanelItem(
163                     trigger=name,
164                     details=st_details,
165                     annotation=st_display_type,
166                     kind=(st_kind, st_icon, st_display_type)))
167             children = item.get('children') or []
168             for child in children:
169                 self.process_document_symbol_recursive(quick_panel_items, child, names)
170 
171     def process_symbol_informations(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:
172         quick_panel_items = []  # type: List[sublime.QuickPanelItem]
173         for item in items:
174             lsp_kind = item['kind']
175             self.regions.append((range_to_region(Range.from_lsp(item['location']['range']), self.view),
176                                  None, get_symbol_scope_from_lsp_kind(lsp_kind)))
177             container = item.get("containerName")
178             st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)
179             quick_panel_items.append(
180                 sublime.QuickPanelItem(
181                     trigger=item["name"],
182                     details=container or "",
183                     annotation=st_display_type,
184                     kind=(st_kind, st_icon, st_display_type)))
185         return quick_panel_items
186 
187 
188 class SymbolQueryInput(sublime_plugin.TextInputHandler):
189 
190     def validate(self, txt: str) -> bool:
191         return txt != ""
192 
193     def placeholder(self) -> str:
194         return "Symbol"
195 
196 
197 class LspWorkspaceSymbolsCommand(LspTextCommand):
198 
199     capability = 'workspaceSymbolProvider'
200 
201     def input(self, _args: Any) -> sublime_plugin.TextInputHandler:
202         return SymbolQueryInput()
203 
204     def run(self, edit: sublime.Edit, symbol_query_input: str = "") -> None:
205         if symbol_query_input:
206             session = self.best_session(self.capability)
207             if session:
208                 self.view.set_status("lsp_workspace_symbols", "Searching for '{}'...".format(symbol_query_input))
209                 request = Request.workspaceSymbol({"query": symbol_query_input})
210                 session.send_request(request, lambda r: self._handle_response(
211                     symbol_query_input, r), self._handle_error)
212 
213     def _format(self, s: Dict[str, Any]) -> str:
214         file_name = os.path.basename(s['location']['uri'])
215         symbol_kind = format_symbol_kind(s["kind"])
216         name = "{} ({}) - {} -- {}".format(s['name'], symbol_kind, s.get('containerName', ""), file_name)
217         return name
218 
219     def _open_file(self, symbols: List[Dict[str, Any]], index: int) -> None:
220         if index != -1:
221             symbol = symbols[index]
222             window = self.view.window()
223             if window:
224                 window.open_file(location_to_encoded_filename(symbol['location']), sublime.ENCODED_POSITION)
225 
226     def _handle_response(self, query: str, response: Optional[List[Dict[str, Any]]]) -> None:
227         self.view.erase_status("lsp_workspace_symbols")
228         if response:
229             matches = response
230             window = self.view.window()
231             if window:
232                 window.show_quick_panel(list(map(self._format, matches)), lambda i: self._open_file(matches, i))
233         else:
234             sublime.message_dialog("No matches found for query string: '{}'".format(query))
235 
236     def _handle_error(self, error: Dict[str, Any]) -> None:
237         self.view.erase_status("lsp_workspace_symbols")
238         reason = error.get("message", "none provided by server :(")
239         msg = "command 'workspace/symbol' failed. Reason: {}".format(reason)
240         sublime.error_message(msg)
241
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/plugin/symbols.py b/plugin/symbols.py
--- a/plugin/symbols.py
+++ b/plugin/symbols.py
@@ -1,5 +1,6 @@
 from .core.protocol import Request, Range
 from .core.registry import LspTextCommand
+from .core.rpc import print_to_status_bar
 from .core.typing import Any, List, Optional, Tuple, Dict, Generator
 from .core.views import location_to_encoded_filename
 from .core.views import range_to_region
@@ -11,6 +12,9 @@
 import sublime_plugin
 
 
+SUPPRESS_INPUT_SETTING_KEY = 'lsp_suppress_input'
+
+
 def unpack_lsp_kind(kind: int) -> Tuple[int, str, str, str]:
     if 1 <= kind <= len(SYMBOL_KINDS):
         return SYMBOL_KINDS[kind - 1]
@@ -75,12 +79,16 @@
         self.is_first_selection = False
 
     def run(self, edit: sublime.Edit) -> None:
+        self.view.settings().set(SUPPRESS_INPUT_SETTING_KEY, True)
         session = self.best_session(self.capability)
         if session:
             session.send_request(
-                Request.documentSymbols({"textDocument": text_document_identifier(self.view)}), self.handle_response)
+                Request.documentSymbols({"textDocument": text_document_identifier(self.view)}),
+                lambda response: sublime.set_timeout(lambda: self.handle_response(response)),
+                lambda error: sublime.set_timeout(lambda: self.handle_response_error(error)))
 
     def handle_response(self, response: Any) -> None:
+        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)
         window = self.view.window()
         if window and isinstance(response, list) and len(response) > 0:
             self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]
@@ -93,6 +101,10 @@
                 self.on_highlighted)
             self.view.run_command("lsp_selection_clear")
 
+    def handle_response_error(self, error: Any) -> None:
+        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)
+        print_to_status_bar(error)
+
     def region(self, index: int) -> sublime.Region:
         return self.regions[index][0]

{"golden_diff": "diff --git a/plugin/symbols.py b/plugin/symbols.py\n--- a/plugin/symbols.py\n+++ b/plugin/symbols.py\n@@ -1,5 +1,6 @@\n from .core.protocol import Request, Range\n from .core.registry import LspTextCommand\n+from .core.rpc import print_to_status_bar\n from .core.typing import Any, List, Optional, Tuple, Dict, Generator\n from .core.views import location_to_encoded_filename\n from .core.views import range_to_region\n@@ -11,6 +12,9 @@\n import sublime_plugin\n \n \n+SUPPRESS_INPUT_SETTING_KEY = 'lsp_suppress_input'\n+\n+\n def unpack_lsp_kind(kind: int) -> Tuple[int, str, str, str]:\n     if 1 <= kind <= len(SYMBOL_KINDS):\n         return SYMBOL_KINDS[kind - 1]\n@@ -75,12 +79,16 @@\n         self.is_first_selection = False\n \n     def run(self, edit: sublime.Edit) -> None:\n+        self.view.settings().set(SUPPRESS_INPUT_SETTING_KEY, True)\n         session = self.best_session(self.capability)\n         if session:\n             session.send_request(\n-                Request.documentSymbols({\"textDocument\": text_document_identifier(self.view)}), self.handle_response)\n+                Request.documentSymbols({\"textDocument\": text_document_identifier(self.view)}),\n+                lambda response: sublime.set_timeout(lambda: self.handle_response(response)),\n+                lambda error: sublime.set_timeout(lambda: self.handle_response_error(error)))\n \n     def handle_response(self, response: Any) -> None:\n+        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)\n         window = self.view.window()\n         if window and isinstance(response, list) and len(response) > 0:\n             self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]\n@@ -93,6 +101,10 @@\n                 self.on_highlighted)\n             self.view.run_command(\"lsp_selection_clear\")\n \n+    def handle_response_error(self, error: Any) -> None:\n+        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)\n+        print_to_status_bar(error)\n+\n     def region(self, index: int) -> sublime.Region:\n         return self.regions[index][0]\n", "issue": "LSP Document Symbols downside compared to native one\n**Describe the bug**\r\nI've been running with `cmd+r` overridden to use Document Symbols from LSP. The functionality is better than native but it has one downside compared to native behavior. Namely, with native, I can trigger the shortcut and start typing immediately. The quick panel appears immediately (synchronously or at least with almost no latency). When using LSP's document symbol, the quick panel only opens after we receive server response so, being used to just start typing my query right away, my query ends up being inserted into the active view instead.\r\n\r\nIdeally, the quick panel would open right away, even before the response comes, but I guess the API might not let us do that.\r\n\r\nAlternatively, we could potentially work around that somehow by capturing user input when the command is triggered and before the quick panel is shown.\n", "before_files": [{"content": "from .core.protocol import Request, Range\nfrom .core.registry import LspTextCommand\nfrom .core.typing import Any, List, Optional, Tuple, Dict, Generator\nfrom .core.views import location_to_encoded_filename\nfrom .core.views import range_to_region\nfrom .core.views import SYMBOL_KINDS\nfrom .core.views import text_document_identifier\nfrom contextlib import contextmanager\nimport os\nimport sublime\nimport sublime_plugin\n\n\ndef unpack_lsp_kind(kind: int) -> Tuple[int, str, str, str]:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1]\n    return sublime.KIND_ID_AMBIGUOUS, \"?\", \"???\", \"comment\"\n\n\ndef format_symbol_kind(kind: int) -> str:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1][2]\n    return str(kind)\n\n\ndef get_symbol_scope_from_lsp_kind(kind: int) -> str:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1][3]\n    return 'comment'\n\n\n@contextmanager\ndef _additional_name(names: List[str], name: str) -> Generator[None, None, None]:\n    names.append(name)\n    yield\n    names.pop(-1)\n\n\nclass LspSelectionClearCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    Selections may not be modified outside the run method of a text command. Thus, to allow modification in an async\n    context we need to have dedicated commands for this.\n\n    https://github.com/sublimehq/sublime_text/issues/485#issuecomment-337480388\n    \"\"\"\n\n    def run(self, _: sublime.Edit) -> None:\n        self.view.sel().clear()\n\n\nclass LspSelectionAddCommand(sublime_plugin.TextCommand):\n\n    def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:\n        for region in regions:\n            self.view.sel().add(sublime.Region(*region))\n\n\nclass LspSelectionSetCommand(sublime_plugin.TextCommand):\n\n    def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:\n        self.view.sel().clear()\n        for region in regions:\n            self.view.sel().add(sublime.Region(*region))\n\n\nclass LspDocumentSymbolsCommand(LspTextCommand):\n\n    capability = 'documentSymbolProvider'\n    REGIONS_KEY = 'lsp_document_symbols'\n\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self.old_regions = []  # type: List[sublime.Region]\n        self.regions = []  # type: List[Tuple[sublime.Region, Optional[sublime.Region], str]]\n        self.is_first_selection = False\n\n    def run(self, edit: sublime.Edit) -> None:\n        session = self.best_session(self.capability)\n        if session:\n            session.send_request(\n                Request.documentSymbols({\"textDocument\": text_document_identifier(self.view)}), self.handle_response)\n\n    def handle_response(self, response: Any) -> None:\n        window = self.view.window()\n        if window and isinstance(response, list) and len(response) > 0:\n            self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]\n            self.is_first_selection = True\n            window.show_quick_panel(\n                self.process_symbols(response),\n                self.on_symbol_selected,\n                sublime.KEEP_OPEN_ON_FOCUS_LOST,\n                0,\n                self.on_highlighted)\n            self.view.run_command(\"lsp_selection_clear\")\n\n    def region(self, index: int) -> sublime.Region:\n        return self.regions[index][0]\n\n    def selection_region(self, index: int) -> Optional[sublime.Region]:\n        return self.regions[index][1]\n\n    def scope(self, index: int) -> str:\n        return self.regions[index][2]\n\n    def on_symbol_selected(self, index: int) -> None:\n        if index == -1:\n            if len(self.old_regions) > 0:\n                self.view.run_command(\"lsp_selection_add\", {\"regions\": [(r.a, r.b) for r in self.old_regions]})\n                self.view.show_at_center(self.old_regions[0].begin())\n        else:\n            region = self.selection_region(index) or self.region(index)\n            self.view.run_command(\"lsp_selection_add\", {\"regions\": [(region.a, region.a)]})\n            self.view.show_at_center(region.a)\n        self.view.erase_regions(self.REGIONS_KEY)\n        self.old_regions.clear()\n        self.regions.clear()\n\n    def on_highlighted(self, index: int) -> None:\n        if self.is_first_selection:\n            self.is_first_selection = False\n            return\n        region = self.region(index)\n        self.view.show_at_center(region.a)\n        self.view.add_regions(self.REGIONS_KEY, [region], self.scope(index), '', sublime.DRAW_NO_FILL)\n\n    def process_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        self.regions.clear()\n        panel_items = []\n        if 'selectionRange' in items[0]:\n            panel_items = self.process_document_symbols(items)\n        else:\n            panel_items = self.process_symbol_informations(items)\n        # Sort both lists in sync according to the range's begin point.\n        sorted_results = zip(*sorted(zip(self.regions, panel_items), key=lambda item: item[0][0].begin()))\n        sorted_regions, sorted_panel_items = sorted_results\n        self.regions = list(sorted_regions)\n        return list(sorted_panel_items)\n\n    def process_document_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        names = []  # type: List[str]\n        for item in items:\n            self.process_document_symbol_recursive(quick_panel_items, item, names)\n        return quick_panel_items\n\n    def process_document_symbol_recursive(self, quick_panel_items: List[sublime.QuickPanelItem], item: Dict[str, Any],\n                                          names: List[str]) -> None:\n        lsp_kind = item[\"kind\"]\n        self.regions.append((range_to_region(Range.from_lsp(item['range']), self.view),\n                             range_to_region(Range.from_lsp(item['selectionRange']), self.view),\n                             get_symbol_scope_from_lsp_kind(lsp_kind)))\n        name = item['name']\n        with _additional_name(names, name):\n            st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)\n            formatted_names = \" > \".join(names)\n            st_details = item.get(\"detail\") or \"\"\n            if st_details:\n                st_details = \"{} | {}\".format(st_details, formatted_names)\n            else:\n                st_details = formatted_names\n            quick_panel_items.append(\n                sublime.QuickPanelItem(\n                    trigger=name,\n                    details=st_details,\n                    annotation=st_display_type,\n                    kind=(st_kind, st_icon, st_display_type)))\n            children = item.get('children') or []\n            for child in children:\n                self.process_document_symbol_recursive(quick_panel_items, child, names)\n\n    def process_symbol_informations(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        for item in items:\n            lsp_kind = item['kind']\n            self.regions.append((range_to_region(Range.from_lsp(item['location']['range']), self.view),\n                                 None, get_symbol_scope_from_lsp_kind(lsp_kind)))\n            container = item.get(\"containerName\")\n            st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)\n            quick_panel_items.append(\n                sublime.QuickPanelItem(\n                    trigger=item[\"name\"],\n                    details=container or \"\",\n                    annotation=st_display_type,\n                    kind=(st_kind, st_icon, st_display_type)))\n        return quick_panel_items\n\n\nclass SymbolQueryInput(sublime_plugin.TextInputHandler):\n\n    def validate(self, txt: str) -> bool:\n        return txt != \"\"\n\n    def placeholder(self) -> str:\n        return \"Symbol\"\n\n\nclass LspWorkspaceSymbolsCommand(LspTextCommand):\n\n    capability = 'workspaceSymbolProvider'\n\n    def input(self, _args: Any) -> sublime_plugin.TextInputHandler:\n        return SymbolQueryInput()\n\n    def run(self, edit: sublime.Edit, symbol_query_input: str = \"\") -> None:\n        if symbol_query_input:\n            session = self.best_session(self.capability)\n            if session:\n                self.view.set_status(\"lsp_workspace_symbols\", \"Searching for '{}'...\".format(symbol_query_input))\n                request = Request.workspaceSymbol({\"query\": symbol_query_input})\n                session.send_request(request, lambda r: self._handle_response(\n                    symbol_query_input, r), self._handle_error)\n\n    def _format(self, s: Dict[str, Any]) -> str:\n        file_name = os.path.basename(s['location']['uri'])\n        symbol_kind = format_symbol_kind(s[\"kind\"])\n        name = \"{} ({}) - {} -- {}\".format(s['name'], symbol_kind, s.get('containerName', \"\"), file_name)\n        return name\n\n    def _open_file(self, symbols: List[Dict[str, Any]], index: int) -> None:\n        if index != -1:\n            symbol = symbols[index]\n            window = self.view.window()\n            if window:\n                window.open_file(location_to_encoded_filename(symbol['location']), sublime.ENCODED_POSITION)\n\n    def _handle_response(self, query: str, response: Optional[List[Dict[str, Any]]]) -> None:\n        self.view.erase_status(\"lsp_workspace_symbols\")\n        if response:\n            matches = response\n            window = self.view.window()\n            if window:\n                window.show_quick_panel(list(map(self._format, matches)), lambda i: self._open_file(matches, i))\n        else:\n            sublime.message_dialog(\"No matches found for query string: '{}'\".format(query))\n\n    def _handle_error(self, error: Dict[str, Any]) -> None:\n        self.view.erase_status(\"lsp_workspace_symbols\")\n        reason = error.get(\"message\", \"none provided by server :(\")\n        msg = \"command 'workspace/symbol' failed. Reason: {}\".format(reason)\n        sublime.error_message(msg)\n", "path": "plugin/symbols.py"}], "after_files": [{"content": "from .core.protocol import Request, Range\nfrom .core.registry import LspTextCommand\nfrom .core.rpc import print_to_status_bar\nfrom .core.typing import Any, List, Optional, Tuple, Dict, Generator\nfrom .core.views import location_to_encoded_filename\nfrom .core.views import range_to_region\nfrom .core.views import SYMBOL_KINDS\nfrom .core.views import text_document_identifier\nfrom contextlib import contextmanager\nimport os\nimport sublime\nimport sublime_plugin\n\n\nSUPPRESS_INPUT_SETTING_KEY = 'lsp_suppress_input'\n\n\ndef unpack_lsp_kind(kind: int) -> Tuple[int, str, str, str]:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1]\n    return sublime.KIND_ID_AMBIGUOUS, \"?\", \"???\", \"comment\"\n\n\ndef format_symbol_kind(kind: int) -> str:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1][2]\n    return str(kind)\n\n\ndef get_symbol_scope_from_lsp_kind(kind: int) -> str:\n    if 1 <= kind <= len(SYMBOL_KINDS):\n        return SYMBOL_KINDS[kind - 1][3]\n    return 'comment'\n\n\n@contextmanager\ndef _additional_name(names: List[str], name: str) -> Generator[None, None, None]:\n    names.append(name)\n    yield\n    names.pop(-1)\n\n\nclass LspSelectionClearCommand(sublime_plugin.TextCommand):\n    \"\"\"\n    Selections may not be modified outside the run method of a text command. Thus, to allow modification in an async\n    context we need to have dedicated commands for this.\n\n    https://github.com/sublimehq/sublime_text/issues/485#issuecomment-337480388\n    \"\"\"\n\n    def run(self, _: sublime.Edit) -> None:\n        self.view.sel().clear()\n\n\nclass LspSelectionAddCommand(sublime_plugin.TextCommand):\n\n    def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:\n        for region in regions:\n            self.view.sel().add(sublime.Region(*region))\n\n\nclass LspSelectionSetCommand(sublime_plugin.TextCommand):\n\n    def run(self, _: sublime.Edit, regions: List[Tuple[int, int]]) -> None:\n        self.view.sel().clear()\n        for region in regions:\n            self.view.sel().add(sublime.Region(*region))\n\n\nclass LspDocumentSymbolsCommand(LspTextCommand):\n\n    capability = 'documentSymbolProvider'\n    REGIONS_KEY = 'lsp_document_symbols'\n\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self.old_regions = []  # type: List[sublime.Region]\n        self.regions = []  # type: List[Tuple[sublime.Region, Optional[sublime.Region], str]]\n        self.is_first_selection = False\n\n    def run(self, edit: sublime.Edit) -> None:\n        self.view.settings().set(SUPPRESS_INPUT_SETTING_KEY, True)\n        session = self.best_session(self.capability)\n        if session:\n            session.send_request(\n                Request.documentSymbols({\"textDocument\": text_document_identifier(self.view)}),\n                lambda response: sublime.set_timeout(lambda: self.handle_response(response)),\n                lambda error: sublime.set_timeout(lambda: self.handle_response_error(error)))\n\n    def handle_response(self, response: Any) -> None:\n        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)\n        window = self.view.window()\n        if window and isinstance(response, list) and len(response) > 0:\n            self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]\n            self.is_first_selection = True\n            window.show_quick_panel(\n                self.process_symbols(response),\n                self.on_symbol_selected,\n                sublime.KEEP_OPEN_ON_FOCUS_LOST,\n                0,\n                self.on_highlighted)\n            self.view.run_command(\"lsp_selection_clear\")\n\n    def handle_response_error(self, error: Any) -> None:\n        self.view.settings().erase(SUPPRESS_INPUT_SETTING_KEY)\n        print_to_status_bar(error)\n\n    def region(self, index: int) -> sublime.Region:\n        return self.regions[index][0]\n\n    def selection_region(self, index: int) -> Optional[sublime.Region]:\n        return self.regions[index][1]\n\n    def scope(self, index: int) -> str:\n        return self.regions[index][2]\n\n    def on_symbol_selected(self, index: int) -> None:\n        if index == -1:\n            if len(self.old_regions) > 0:\n                self.view.run_command(\"lsp_selection_add\", {\"regions\": [(r.a, r.b) for r in self.old_regions]})\n                self.view.show_at_center(self.old_regions[0].begin())\n        else:\n            region = self.selection_region(index) or self.region(index)\n            self.view.run_command(\"lsp_selection_add\", {\"regions\": [(region.a, region.a)]})\n            self.view.show_at_center(region.a)\n        self.view.erase_regions(self.REGIONS_KEY)\n        self.old_regions.clear()\n        self.regions.clear()\n\n    def on_highlighted(self, index: int) -> None:\n        if self.is_first_selection:\n            self.is_first_selection = False\n            return\n        region = self.region(index)\n        self.view.show_at_center(region.a)\n        self.view.add_regions(self.REGIONS_KEY, [region], self.scope(index), '', sublime.DRAW_NO_FILL)\n\n    def process_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        self.regions.clear()\n        panel_items = []\n        if 'selectionRange' in items[0]:\n            panel_items = self.process_document_symbols(items)\n        else:\n            panel_items = self.process_symbol_informations(items)\n        # Sort both lists in sync according to the range's begin point.\n        sorted_results = zip(*sorted(zip(self.regions, panel_items), key=lambda item: item[0][0].begin()))\n        sorted_regions, sorted_panel_items = sorted_results\n        self.regions = list(sorted_regions)\n        return list(sorted_panel_items)\n\n    def process_document_symbols(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        names = []  # type: List[str]\n        for item in items:\n            self.process_document_symbol_recursive(quick_panel_items, item, names)\n        return quick_panel_items\n\n    def process_document_symbol_recursive(self, quick_panel_items: List[sublime.QuickPanelItem], item: Dict[str, Any],\n                                          names: List[str]) -> None:\n        lsp_kind = item[\"kind\"]\n        self.regions.append((range_to_region(Range.from_lsp(item['range']), self.view),\n                             range_to_region(Range.from_lsp(item['selectionRange']), self.view),\n                             get_symbol_scope_from_lsp_kind(lsp_kind)))\n        name = item['name']\n        with _additional_name(names, name):\n            st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)\n            formatted_names = \" > \".join(names)\n            st_details = item.get(\"detail\") or \"\"\n            if st_details:\n                st_details = \"{} | {}\".format(st_details, formatted_names)\n            else:\n                st_details = formatted_names\n            quick_panel_items.append(\n                sublime.QuickPanelItem(\n                    trigger=name,\n                    details=st_details,\n                    annotation=st_display_type,\n                    kind=(st_kind, st_icon, st_display_type)))\n            children = item.get('children') or []\n            for child in children:\n                self.process_document_symbol_recursive(quick_panel_items, child, names)\n\n    def process_symbol_informations(self, items: List[Dict[str, Any]]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        for item in items:\n            lsp_kind = item['kind']\n            self.regions.append((range_to_region(Range.from_lsp(item['location']['range']), self.view),\n                                 None, get_symbol_scope_from_lsp_kind(lsp_kind)))\n            container = item.get(\"containerName\")\n            st_kind, st_icon, st_display_type, _ = unpack_lsp_kind(lsp_kind)\n            quick_panel_items.append(\n                sublime.QuickPanelItem(\n                    trigger=item[\"name\"],\n                    details=container or \"\",\n                    annotation=st_display_type,\n                    kind=(st_kind, st_icon, st_display_type)))\n        return quick_panel_items\n\n\nclass SymbolQueryInput(sublime_plugin.TextInputHandler):\n\n    def validate(self, txt: str) -> bool:\n        return txt != \"\"\n\n    def placeholder(self) -> str:\n        return \"Symbol\"\n\n\nclass LspWorkspaceSymbolsCommand(LspTextCommand):\n\n    capability = 'workspaceSymbolProvider'\n\n    def input(self, _args: Any) -> sublime_plugin.TextInputHandler:\n        return SymbolQueryInput()\n\n    def run(self, edit: sublime.Edit, symbol_query_input: str = \"\") -> None:\n        if symbol_query_input:\n            session = self.best_session(self.capability)\n            if session:\n                self.view.set_status(\"lsp_workspace_symbols\", \"Searching for '{}'...\".format(symbol_query_input))\n                request = Request.workspaceSymbol({\"query\": symbol_query_input})\n                session.send_request(request, lambda r: self._handle_response(\n                    symbol_query_input, r), self._handle_error)\n\n    def _format(self, s: Dict[str, Any]) -> str:\n        file_name = os.path.basename(s['location']['uri'])\n        symbol_kind = format_symbol_kind(s[\"kind\"])\n        name = \"{} ({}) - {} -- {}\".format(s['name'], symbol_kind, s.get('containerName', \"\"), file_name)\n        return name\n\n    def _open_file(self, symbols: List[Dict[str, Any]], index: int) -> None:\n        if index != -1:\n            symbol = symbols[index]\n            window = self.view.window()\n            if window:\n                window.open_file(location_to_encoded_filename(symbol['location']), sublime.ENCODED_POSITION)\n\n    def _handle_response(self, query: str, response: Optional[List[Dict[str, Any]]]) -> None:\n        self.view.erase_status(\"lsp_workspace_symbols\")\n        if response:\n            matches = response\n            window = self.view.window()\n            if window:\n                window.show_quick_panel(list(map(self._format, matches)), lambda i: self._open_file(matches, i))\n        else:\n            sublime.message_dialog(\"No matches found for query string: '{}'\".format(query))\n\n    def _handle_error(self, error: Dict[str, Any]) -> None:\n        self.view.erase_status(\"lsp_workspace_symbols\")\n        reason = error.get(\"message\", \"none provided by server :(\")\n        msg = \"command 'workspace/symbol' failed. Reason: {}\".format(reason)\n        sublime.error_message(msg)\n", "path": "plugin/symbols.py"}]}