We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`lsp_document_symbols` should initially focus on current symbol under caret
Sublime's default implementation of Goto Symbol pops up with current symbol having focus in the dropdown list, this way I can use up/down arrows to go to prev/next symbols (since Sublime doesn't have goto next/prev symbol features built-in, this is imo a superior way to mimic that feature).

LSP is capable of finding all the symbols for a given language but the problem is, `lsp_document_symbols` commands focuses the first symbol in the file, so I can't easily use the arrow keys to browse the next/previous symbols.

So it would be better if LSP's replacement Goto Symbol popup focused the symbol of the current scope / the symbol under the caret.

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

{"golden_diff": "diff --git a/plugin/symbols.py b/plugin/symbols.py\n--- a/plugin/symbols.py\n+++ b/plugin/symbols.py\n@@ -94,7 +94,6 @@\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, event: Optional[Dict[str, Any]] = None) -> None:\n         self.view.settings().set(SUPPRESS_INPUT_SETTING_KEY, True)\n@@ -109,13 +108,22 @@\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+            panel_items = self.process_symbols(response)\n             self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]\n-            self.is_first_selection = True\n+            # Find region that is either intersecting or before to the current selection end.\n+            selected_index = 0\n+            if len(self.old_regions):\n+                first_selection = self.old_regions[0]\n+                for i, (r, _, _) in enumerate(self.regions):\n+                    if r.begin() <= first_selection.b:\n+                        selected_index = i\n+                    else:\n+                        break\n             window.show_quick_panel(\n-                self.process_symbols(response),\n+                panel_items,\n                 self.on_symbol_selected,\n                 sublime.KEEP_OPEN_ON_FOCUS_LOST,\n-                0,\n+                selected_index,\n                 self.on_highlighted)\n             self.view.run_command(\"lsp_selection_clear\")\n \n@@ -146,9 +154,6 @@\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", "issue": "`lsp_document_symbols` should initially focus on current symbol under caret\nSublime's default implementation of Goto Symbol pops up with current symbol having focus in the dropdown list, this way I can use up/down arrows to go to prev/next symbols (since Sublime doesn't have goto next/prev symbol features built-in, this is imo a superior way to mimic that feature).\r\n\r\nLSP is capable of finding all the symbols for a given language but the problem is, `lsp_document_symbols` commands focuses the first symbol in the file, so I can't easily use the arrow keys to browse the next/previous symbols.\r\n\r\nSo it would be better if LSP's replacement Goto Symbol popup focused the symbol of the current scope / the symbol under the caret.\n", "before_files": [{"content": "import weakref\nfrom .core.protocol import Request, DocumentSymbol, SymbolInformation, SymbolKind, SymbolTag\nfrom .core.registry import LspTextCommand\nfrom .core.sessions import print_to_status_bar\nfrom .core.typing import Any, List, Optional, Tuple, Dict, Generator, Union, cast\nfrom .core.views import range_to_region\nfrom .core.views import SublimeKind\nfrom .core.views import SYMBOL_KIND_SCOPES\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: SymbolKind) -> SublimeKind:\n    return SYMBOL_KINDS.get(kind, sublime.KIND_AMBIGUOUS)\n\n\ndef format_symbol_kind(kind: SymbolKind) -> str:\n    return SYMBOL_KINDS.get(kind, (None, None, str(kind)))[2]\n\n\ndef get_symbol_scope_from_lsp_kind(kind: SymbolKind) -> str:\n    return SYMBOL_KIND_SCOPES.get(kind, \"comment\")\n\n\ndef symbol_information_to_quick_panel_item(\n    item: SymbolInformation,\n    show_file_name: bool = True\n) -> sublime.QuickPanelItem:\n    st_kind, st_icon, st_display_type = unpack_lsp_kind(item['kind'])\n    tags = item.get(\"tags\") or []\n    if SymbolTag.Deprecated in tags:\n        st_display_type = \"\u26a0 {} - Deprecated\".format(st_display_type)\n    container = item.get(\"containerName\") or \"\"\n    details = []  # List[str]\n    if container:\n        details.append(container)\n    if show_file_name:\n        file_name = os.path.basename(item['location']['uri'])\n        details.append(file_name)\n    return sublime.QuickPanelItem(\n            trigger=item[\"name\"],\n            details=details,\n            annotation=st_display_type,\n            kind=(st_kind, st_icon, st_display_type))\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, event: Optional[Dict[str, Any]] = None) -> 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.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: Union[List[DocumentSymbol], List[SymbolInformation], None]) -> 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(\n            self,\n            items: Union[List[DocumentSymbol], List[SymbolInformation]]\n    ) -> List[sublime.QuickPanelItem]:\n        self.regions.clear()\n        panel_items = []\n        if 'selectionRange' in items[0]:\n            items = cast(List[DocumentSymbol], items)\n            panel_items = self.process_document_symbols(items)\n        else:\n            items = cast(List[SymbolInformation], items)\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)  # type: ignore\n        return list(sorted_panel_items)  # type: ignore\n\n    def process_document_symbols(self, items: List[DocumentSymbol]) -> 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: DocumentSymbol,\n                                          names: List[str]) -> None:\n        lsp_kind = item[\"kind\"]\n        self.regions.append((range_to_region(item['range'], self.view),\n                             range_to_region(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            tags = item.get(\"tags\") or []\n            if SymbolTag.Deprecated in tags:\n                st_display_type = \"\u26a0 {} - Deprecated\".format(st_display_type)\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 []  # type: List[DocumentSymbol]\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[SymbolInformation]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        for item in items:\n            self.regions.append((range_to_region(item['location']['range'], self.view),\n                                 None, get_symbol_scope_from_lsp_kind(item['kind'])))\n            quick_panel_item = symbol_information_to_quick_panel_item(item, show_file_name=False)\n            quick_panel_items.append(quick_panel_item)\n        return quick_panel_items\n\n\nclass SymbolQueryInput(sublime_plugin.TextInputHandler):\n    def want_event(self) -> bool:\n        return False\n\n    def placeholder(self) -> str:\n        return \"Enter symbol name\"\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, event: Optional[Any] = None) -> None:\n        session = self.best_session(self.capability)\n        if session:\n            self.weaksession = weakref.ref(session)\n            session.send_request(\n                Request.workspaceSymbol({\"query\": symbol_query_input}),\n                lambda r: self._handle_response(symbol_query_input, r),\n                self._handle_error)\n\n    def _open_file(self, symbols: List[SymbolInformation], index: int) -> None:\n        if index != -1:\n            session = self.weaksession()\n            if session:\n                session.open_location_async(symbols[index]['location'], sublime.ENCODED_POSITION)\n\n    def _handle_response(self, query: str, response: Union[List[SymbolInformation], None]) -> None:\n        if response:\n            matches = response\n            window = self.view.window()\n            if window:\n                window.show_quick_panel(\n                    list(map(symbol_information_to_quick_panel_item, matches)),\n                    lambda i: self._open_file(matches, i))\n        else:\n            sublime.message_dialog(\"No matches found for query: '{}'\".format(query))\n\n    def _handle_error(self, error: Dict[str, Any]) -> None:\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": "import weakref\nfrom .core.protocol import Request, DocumentSymbol, SymbolInformation, SymbolKind, SymbolTag\nfrom .core.registry import LspTextCommand\nfrom .core.sessions import print_to_status_bar\nfrom .core.typing import Any, List, Optional, Tuple, Dict, Generator, Union, cast\nfrom .core.views import range_to_region\nfrom .core.views import SublimeKind\nfrom .core.views import SYMBOL_KIND_SCOPES\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: SymbolKind) -> SublimeKind:\n    return SYMBOL_KINDS.get(kind, sublime.KIND_AMBIGUOUS)\n\n\ndef format_symbol_kind(kind: SymbolKind) -> str:\n    return SYMBOL_KINDS.get(kind, (None, None, str(kind)))[2]\n\n\ndef get_symbol_scope_from_lsp_kind(kind: SymbolKind) -> str:\n    return SYMBOL_KIND_SCOPES.get(kind, \"comment\")\n\n\ndef symbol_information_to_quick_panel_item(\n    item: SymbolInformation,\n    show_file_name: bool = True\n) -> sublime.QuickPanelItem:\n    st_kind, st_icon, st_display_type = unpack_lsp_kind(item['kind'])\n    tags = item.get(\"tags\") or []\n    if SymbolTag.Deprecated in tags:\n        st_display_type = \"\u26a0 {} - Deprecated\".format(st_display_type)\n    container = item.get(\"containerName\") or \"\"\n    details = []  # List[str]\n    if container:\n        details.append(container)\n    if show_file_name:\n        file_name = os.path.basename(item['location']['uri'])\n        details.append(file_name)\n    return sublime.QuickPanelItem(\n            trigger=item[\"name\"],\n            details=details,\n            annotation=st_display_type,\n            kind=(st_kind, st_icon, st_display_type))\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\n    def run(self, edit: sublime.Edit, event: Optional[Dict[str, Any]] = None) -> 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.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: Union[List[DocumentSymbol], List[SymbolInformation], None]) -> 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            panel_items = self.process_symbols(response)\n            self.old_regions = [sublime.Region(r.a, r.b) for r in self.view.sel()]\n            # Find region that is either intersecting or before to the current selection end.\n            selected_index = 0\n            if len(self.old_regions):\n                first_selection = self.old_regions[0]\n                for i, (r, _, _) in enumerate(self.regions):\n                    if r.begin() <= first_selection.b:\n                        selected_index = i\n                    else:\n                        break\n            window.show_quick_panel(\n                panel_items,\n                self.on_symbol_selected,\n                sublime.KEEP_OPEN_ON_FOCUS_LOST,\n                selected_index,\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        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(\n            self,\n            items: Union[List[DocumentSymbol], List[SymbolInformation]]\n    ) -> List[sublime.QuickPanelItem]:\n        self.regions.clear()\n        panel_items = []\n        if 'selectionRange' in items[0]:\n            items = cast(List[DocumentSymbol], items)\n            panel_items = self.process_document_symbols(items)\n        else:\n            items = cast(List[SymbolInformation], items)\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)  # type: ignore\n        return list(sorted_panel_items)  # type: ignore\n\n    def process_document_symbols(self, items: List[DocumentSymbol]) -> 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: DocumentSymbol,\n                                          names: List[str]) -> None:\n        lsp_kind = item[\"kind\"]\n        self.regions.append((range_to_region(item['range'], self.view),\n                             range_to_region(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            tags = item.get(\"tags\") or []\n            if SymbolTag.Deprecated in tags:\n                st_display_type = \"\u26a0 {} - Deprecated\".format(st_display_type)\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 []  # type: List[DocumentSymbol]\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[SymbolInformation]) -> List[sublime.QuickPanelItem]:\n        quick_panel_items = []  # type: List[sublime.QuickPanelItem]\n        for item in items:\n            self.regions.append((range_to_region(item['location']['range'], self.view),\n                                 None, get_symbol_scope_from_lsp_kind(item['kind'])))\n            quick_panel_item = symbol_information_to_quick_panel_item(item, show_file_name=False)\n            quick_panel_items.append(quick_panel_item)\n        return quick_panel_items\n\n\nclass SymbolQueryInput(sublime_plugin.TextInputHandler):\n    def want_event(self) -> bool:\n        return False\n\n    def placeholder(self) -> str:\n        return \"Enter symbol name\"\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, event: Optional[Any] = None) -> None:\n        session = self.best_session(self.capability)\n        if session:\n            self.weaksession = weakref.ref(session)\n            session.send_request(\n                Request.workspaceSymbol({\"query\": symbol_query_input}),\n                lambda r: self._handle_response(symbol_query_input, r),\n                self._handle_error)\n\n    def _open_file(self, symbols: List[SymbolInformation], index: int) -> None:\n        if index != -1:\n            session = self.weaksession()\n            if session:\n                session.open_location_async(symbols[index]['location'], sublime.ENCODED_POSITION)\n\n    def _handle_response(self, query: str, response: Union[List[SymbolInformation], None]) -> None:\n        if response:\n            matches = response\n            window = self.view.window()\n            if window:\n                window.show_quick_panel(\n                    list(map(symbol_information_to_quick_panel_item, matches)),\n                    lambda i: self._open_file(matches, i))\n        else:\n            sublime.message_dialog(\"No matches found for query: '{}'\".format(query))\n\n    def _handle_error(self, error: Dict[str, Any]) -> None:\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"}]}