We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Forced-break in hover popup can break syntax highlighting
Using: OSX / typescript-language-server

Line-break, that LSP forces in the popup, can cause syntax highlighting to break. For example, if breaking a plain string in JS syntax.

<img width="512" alt="line-break" src="https://user-images.githubusercontent.com/153197/72525594-cfa7ff00-3864-11ea-9e8a-c183e07995a1.png">

Notice that in the screenshot the whole string should have a yellow color. Syntax highlighting breaks because line break within a string is not a valid syntax.

--- 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/hover.py`
Content:
```
1 import mdpopups
2 import sublime
3 import sublime_plugin
4 import webbrowser
5 import os
6 import textwrap
7 from html import escape
8 from .code_actions import actions_manager, run_code_action_or_command
9 from .code_actions import CodeActionOrCommand
10 from .core.configurations import is_supported_syntax
11 from .core.popups import popups
12 from .core.protocol import Request, DiagnosticSeverity, Diagnostic, DiagnosticRelatedInformation, Point
13 from .core.registry import session_for_view, LspTextCommand, windows
14 from .core.settings import client_configs, settings
15 from .core.typing import List, Optional, Any, Dict
16 from .core.views import text_document_position_params
17 from .diagnostics import filter_by_point, view_diagnostics
18 
19 
20 SUBLIME_WORD_MASK = 515
21 
22 
23 class HoverHandler(sublime_plugin.ViewEventListener):
24     def __init__(self, view: sublime.View) -> None:
25         self.view = view
26 
27     @classmethod
28     def is_applicable(cls, view_settings: dict) -> bool:
29         if 'hover' in settings.disabled_capabilities:
30             return False
31         syntax = view_settings.get('syntax')
32         if syntax:
33             return is_supported_syntax(syntax, client_configs.all)
34         else:
35             return False
36 
37     def on_hover(self, point: int, hover_zone: int) -> None:
38         if hover_zone != sublime.HOVER_TEXT or self.view.is_popup_visible():
39             return
40         self.view.run_command("lsp_hover", {"point": point})
41 
42 
43 _test_contents = []  # type: List[str]
44 
45 
46 class_for_severity = {
47     DiagnosticSeverity.Error: 'errors',
48     DiagnosticSeverity.Warning: 'warnings',
49     DiagnosticSeverity.Information: 'info',
50     DiagnosticSeverity.Hint: 'hints'
51 }
52 
53 
54 class GotoKind:
55 
56     __slots__ = ("lsp_name", "label", "subl_cmd_name")
57 
58     def __init__(self, lsp_name: str, label: str, subl_cmd_name: str) -> None:
59         self.lsp_name = lsp_name
60         self.label = label
61         self.subl_cmd_name = subl_cmd_name
62 
63 
64 goto_kinds = [
65     GotoKind("definition", "Definition", "definition"),
66     GotoKind("typeDefinition", "Type Definition", "type_definition"),
67     GotoKind("declaration", "Declaration", "declaration"),
68     GotoKind("implementation", "Implementation", "implementation")
69 ]
70 
71 
72 class LspHoverCommand(LspTextCommand):
73     def __init__(self, view: sublime.View) -> None:
74         super().__init__(view)
75         self._base_dir = None   # type: Optional[str]
76 
77     def is_likely_at_symbol(self, point: int) -> bool:
78         word_at_sel = self.view.classify(point)
79         return bool(word_at_sel & SUBLIME_WORD_MASK)
80 
81     def run(self, edit: sublime.Edit, point: Optional[int] = None) -> None:
82         hover_point = point or self.view.sel()[0].begin()
83         self._base_dir = windows.lookup(self.view.window()).get_project_path(self.view.file_name() or "")
84 
85         self._hover = None  # type: Optional[Any]
86         self._actions_by_config = {}  # type: Dict[str, List[CodeActionOrCommand]]
87         self._diagnostics_by_config = {}  # type: Dict[str, List[Diagnostic]]
88 
89         if self.is_likely_at_symbol(hover_point):
90             self.request_symbol_hover(hover_point)
91 
92         self._diagnostics_by_config = filter_by_point(view_diagnostics(self.view),
93                                                       Point(*self.view.rowcol(hover_point)))
94         if self._diagnostics_by_config:
95             self.request_code_actions(hover_point)
96             self.request_show_hover(hover_point)
97 
98     def request_symbol_hover(self, point: int) -> None:
99         # todo: session_for_view looks up windowmanager twice (config and for sessions)
100         # can we memoize some part (eg. where no point is provided?)
101         session = session_for_view(self.view, 'hoverProvider', point)
102         if session:
103             document_position = text_document_position_params(self.view, point)
104             if session.client:
105                 session.client.send_request(
106                     Request.hover(document_position),
107                     lambda response: self.handle_response(response, point))
108 
109     def request_code_actions(self, point: int) -> None:
110         actions_manager.request(self.view, point, lambda response: self.handle_code_actions(response, point),
111                                 self._diagnostics_by_config)
112 
113     def handle_code_actions(self, responses: Dict[str, List[CodeActionOrCommand]], point: int) -> None:
114         self._actions_by_config = responses
115         self.request_show_hover(point)
116 
117     def handle_response(self, response: Optional[Any], point: int) -> None:
118         self._hover = response
119         self.request_show_hover(point)
120 
121     def symbol_actions_content(self) -> str:
122         actions = []
123         for goto_kind in goto_kinds:
124             if self.has_client_with_capability(goto_kind.lsp_name + "Provider"):
125                 actions.append("<a href='{}'>{}</a>".format(goto_kind.lsp_name, goto_kind.label))
126         if self.has_client_with_capability('referencesProvider'):
127             actions.append("<a href='{}'>{}</a>".format('references', 'References'))
128         if self.has_client_with_capability('renameProvider'):
129             actions.append("<a href='{}'>{}</a>".format('rename', 'Rename'))
130         return "<p>" + " | ".join(actions) + "</p>"
131 
132     def format_diagnostic_related_info(self, info: DiagnosticRelatedInformation) -> str:
133         file_path = info.location.file_path
134         if self._base_dir and file_path.startswith(self._base_dir):
135             file_path = os.path.relpath(file_path, self._base_dir)
136         location = "{}:{}:{}".format(file_path, info.location.range.start.row+1, info.location.range.start.col+1)
137         return "<a href='location:{}'>{}</a>: {}".format(location, location, escape(info.message))
138 
139     def format_diagnostic(self, diagnostic: 'Diagnostic') -> str:
140         diagnostic_message = escape(diagnostic.message, False).replace('\n', '<br>')
141         related_infos = [self.format_diagnostic_related_info(info) for info in diagnostic.related_info]
142         related_content = "<pre class='related_info'>" + "<br>".join(related_infos) + "</pre>" if related_infos else ""
143 
144         if diagnostic.source:
145             return "<pre class=\"{}\">[{}] {}{}</pre>".format(class_for_severity[diagnostic.severity],
146                                                               diagnostic.source, diagnostic_message, related_content)
147         else:
148             return "<pre class=\"{}\">{}{}</pre>".format(class_for_severity[diagnostic.severity], diagnostic_message,
149                                                          related_content)
150 
151     def diagnostics_content(self) -> str:
152         formatted = []
153         for config_name in self._diagnostics_by_config:
154             by_severity = {}  # type: Dict[int, List[str]]
155             formatted.append("<div class='diagnostics'>")
156             for diagnostic in self._diagnostics_by_config[config_name]:
157                 by_severity.setdefault(diagnostic.severity, []).append(self.format_diagnostic(diagnostic))
158 
159             for severity, items in by_severity.items():
160                 formatted.append("<div>")
161                 formatted.extend(items)
162                 formatted.append("</div>")
163 
164             if config_name in self._actions_by_config:
165                 action_count = len(self._actions_by_config[config_name])
166                 if action_count > 0:
167                     formatted.append("<div class=\"actions\"><a href='{}:{}'>{} ({})</a></div>".format(
168                         'code-actions', config_name, 'Code Actions', action_count))
169 
170             formatted.append("</div>")
171 
172         return "".join(formatted)
173 
174     def hover_content(self) -> str:
175         contents = []  # type: List[Any]
176         if isinstance(self._hover, dict):
177             response_content = self._hover.get('contents')
178             if response_content:
179                 if isinstance(response_content, list):
180                     contents = response_content
181                 else:
182                     contents = [response_content]
183 
184         formatted = []
185         for item in contents:
186             value = ""
187             language = None
188             if isinstance(item, str):
189                 value = item
190             else:
191                 value = item.get("value")
192                 language = item.get("language")
193 
194             if '\n' not in value:
195                 value = "\n".join(textwrap.wrap(value, 80))
196 
197             if language:
198                 formatted.append("```{}\n{}\n```\n".format(language, value))
199             else:
200                 formatted.append(value)
201 
202         if formatted:
203             return mdpopups.md2html(self.view, "\n".join(formatted))
204 
205         return ""
206 
207     def request_show_hover(self, point: int) -> None:
208         sublime.set_timeout(lambda: self.show_hover(point), 50)
209 
210     def show_hover(self, point: int) -> None:
211         contents = self.diagnostics_content() + self.hover_content()
212         if contents and settings.show_symbol_action_links:
213             contents += self.symbol_actions_content()
214 
215         _test_contents.clear()
216         _test_contents.append(contents)  # for testing only
217 
218         if contents:
219             mdpopups.show_popup(
220                 self.view,
221                 contents,
222                 css=popups.stylesheet,
223                 md=False,
224                 flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
225                 location=point,
226                 wrapper_class=popups.classname,
227                 max_width=800,
228                 on_navigate=lambda href: self.on_hover_navigate(href, point))
229 
230     def on_hover_navigate(self, href: str, point: int) -> None:
231         for goto_kind in goto_kinds:
232             if href == goto_kind.lsp_name:
233                 self.run_command_from_point(point, "lsp_symbol_" + goto_kind.subl_cmd_name)
234                 return
235         if href == 'references':
236             self.run_command_from_point(point, "lsp_symbol_references")
237         elif href == 'rename':
238             self.run_command_from_point(point, "lsp_symbol_rename")
239         elif href.startswith('code-actions'):
240             _, config_name = href.split(":")
241             titles = [command["title"] for command in self._actions_by_config[config_name]]
242             sel = self.view.sel()
243             sel.clear()
244             sel.add(sublime.Region(point, point))
245 
246             self.view.show_popup_menu(titles, lambda i: self.handle_code_action_select(config_name, i))
247         elif href.startswith('location'):
248             _, file_path, location = href.split(":", 2)
249             file_path = os.path.join(self._base_dir, file_path) if self._base_dir else file_path
250             window = self.view.window()
251             if window:
252                 window.open_file(file_path + ":" + location, sublime.ENCODED_POSITION | sublime.TRANSIENT)
253         else:
254             webbrowser.open_new_tab(href)
255 
256     def handle_code_action_select(self, config_name: str, index: int) -> None:
257         if index > -1:
258             selected = self._actions_by_config[config_name][index]
259             run_code_action_or_command(self.view, config_name, selected)
260 
261     def run_command_from_point(self, point: int, command_name: str, args: Optional[Any] = None) -> None:
262         sel = self.view.sel()
263         sel.clear()
264         sel.add(sublime.Region(point, point))
265         self.view.run_command(command_name, args)
266
```
--- 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/hover.py b/plugin/hover.py
--- a/plugin/hover.py
+++ b/plugin/hover.py
@@ -3,7 +3,6 @@
 import sublime_plugin
 import webbrowser
 import os
-import textwrap
 from html import escape
 from .code_actions import actions_manager, run_code_action_or_command
 from .code_actions import CodeActionOrCommand
@@ -191,16 +190,14 @@
                 value = item.get("value")
                 language = item.get("language")
 
-            if '\n' not in value:
-                value = "\n".join(textwrap.wrap(value, 80))
-
             if language:
                 formatted.append("```{}\n{}\n```\n".format(language, value))
             else:
                 formatted.append(value)
 
         if formatted:
-            return mdpopups.md2html(self.view, "\n".join(formatted))
+            frontmatter_config = mdpopups.format_frontmatter({'allow_code_wrap': True})
+            return mdpopups.md2html(self.view, frontmatter_config + "\n".join(formatted))
 
         return ""

{"golden_diff": "diff --git a/plugin/hover.py b/plugin/hover.py\n--- a/plugin/hover.py\n+++ b/plugin/hover.py\n@@ -3,7 +3,6 @@\n import sublime_plugin\n import webbrowser\n import os\n-import textwrap\n from html import escape\n from .code_actions import actions_manager, run_code_action_or_command\n from .code_actions import CodeActionOrCommand\n@@ -191,16 +190,14 @@\n                 value = item.get(\"value\")\n                 language = item.get(\"language\")\n \n-            if '\\n' not in value:\n-                value = \"\\n\".join(textwrap.wrap(value, 80))\n-\n             if language:\n                 formatted.append(\"```{}\\n{}\\n```\\n\".format(language, value))\n             else:\n                 formatted.append(value)\n \n         if formatted:\n-            return mdpopups.md2html(self.view, \"\\n\".join(formatted))\n+            frontmatter_config = mdpopups.format_frontmatter({'allow_code_wrap': True})\n+            return mdpopups.md2html(self.view, frontmatter_config + \"\\n\".join(formatted))\n \n         return \"\"\n", "issue": "Forced-break in hover popup can break syntax highlighting\nUsing: OSX / typescript-language-server\r\n\r\nLine-break, that LSP forces in the popup, can cause syntax highlighting to break. For example, if breaking a plain string in JS syntax.\r\n\r\n<img width=\"512\" alt=\"line-break\" src=\"https://user-images.githubusercontent.com/153197/72525594-cfa7ff00-3864-11ea-9e8a-c183e07995a1.png\">\r\n\r\nNotice that in the screenshot the whole string should have a yellow color. Syntax highlighting breaks because line break within a string is not a valid syntax.\n", "before_files": [{"content": "import mdpopups\nimport sublime\nimport sublime_plugin\nimport webbrowser\nimport os\nimport textwrap\nfrom html import escape\nfrom .code_actions import actions_manager, run_code_action_or_command\nfrom .code_actions import CodeActionOrCommand\nfrom .core.configurations import is_supported_syntax\nfrom .core.popups import popups\nfrom .core.protocol import Request, DiagnosticSeverity, Diagnostic, DiagnosticRelatedInformation, Point\nfrom .core.registry import session_for_view, LspTextCommand, windows\nfrom .core.settings import client_configs, settings\nfrom .core.typing import List, Optional, Any, Dict\nfrom .core.views import text_document_position_params\nfrom .diagnostics import filter_by_point, view_diagnostics\n\n\nSUBLIME_WORD_MASK = 515\n\n\nclass HoverHandler(sublime_plugin.ViewEventListener):\n    def __init__(self, view: sublime.View) -> None:\n        self.view = view\n\n    @classmethod\n    def is_applicable(cls, view_settings: dict) -> bool:\n        if 'hover' in settings.disabled_capabilities:\n            return False\n        syntax = view_settings.get('syntax')\n        if syntax:\n            return is_supported_syntax(syntax, client_configs.all)\n        else:\n            return False\n\n    def on_hover(self, point: int, hover_zone: int) -> None:\n        if hover_zone != sublime.HOVER_TEXT or self.view.is_popup_visible():\n            return\n        self.view.run_command(\"lsp_hover\", {\"point\": point})\n\n\n_test_contents = []  # type: List[str]\n\n\nclass_for_severity = {\n    DiagnosticSeverity.Error: 'errors',\n    DiagnosticSeverity.Warning: 'warnings',\n    DiagnosticSeverity.Information: 'info',\n    DiagnosticSeverity.Hint: 'hints'\n}\n\n\nclass GotoKind:\n\n    __slots__ = (\"lsp_name\", \"label\", \"subl_cmd_name\")\n\n    def __init__(self, lsp_name: str, label: str, subl_cmd_name: str) -> None:\n        self.lsp_name = lsp_name\n        self.label = label\n        self.subl_cmd_name = subl_cmd_name\n\n\ngoto_kinds = [\n    GotoKind(\"definition\", \"Definition\", \"definition\"),\n    GotoKind(\"typeDefinition\", \"Type Definition\", \"type_definition\"),\n    GotoKind(\"declaration\", \"Declaration\", \"declaration\"),\n    GotoKind(\"implementation\", \"Implementation\", \"implementation\")\n]\n\n\nclass LspHoverCommand(LspTextCommand):\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self._base_dir = None   # type: Optional[str]\n\n    def is_likely_at_symbol(self, point: int) -> bool:\n        word_at_sel = self.view.classify(point)\n        return bool(word_at_sel & SUBLIME_WORD_MASK)\n\n    def run(self, edit: sublime.Edit, point: Optional[int] = None) -> None:\n        hover_point = point or self.view.sel()[0].begin()\n        self._base_dir = windows.lookup(self.view.window()).get_project_path(self.view.file_name() or \"\")\n\n        self._hover = None  # type: Optional[Any]\n        self._actions_by_config = {}  # type: Dict[str, List[CodeActionOrCommand]]\n        self._diagnostics_by_config = {}  # type: Dict[str, List[Diagnostic]]\n\n        if self.is_likely_at_symbol(hover_point):\n            self.request_symbol_hover(hover_point)\n\n        self._diagnostics_by_config = filter_by_point(view_diagnostics(self.view),\n                                                      Point(*self.view.rowcol(hover_point)))\n        if self._diagnostics_by_config:\n            self.request_code_actions(hover_point)\n            self.request_show_hover(hover_point)\n\n    def request_symbol_hover(self, point: int) -> None:\n        # todo: session_for_view looks up windowmanager twice (config and for sessions)\n        # can we memoize some part (eg. where no point is provided?)\n        session = session_for_view(self.view, 'hoverProvider', point)\n        if session:\n            document_position = text_document_position_params(self.view, point)\n            if session.client:\n                session.client.send_request(\n                    Request.hover(document_position),\n                    lambda response: self.handle_response(response, point))\n\n    def request_code_actions(self, point: int) -> None:\n        actions_manager.request(self.view, point, lambda response: self.handle_code_actions(response, point),\n                                self._diagnostics_by_config)\n\n    def handle_code_actions(self, responses: Dict[str, List[CodeActionOrCommand]], point: int) -> None:\n        self._actions_by_config = responses\n        self.request_show_hover(point)\n\n    def handle_response(self, response: Optional[Any], point: int) -> None:\n        self._hover = response\n        self.request_show_hover(point)\n\n    def symbol_actions_content(self) -> str:\n        actions = []\n        for goto_kind in goto_kinds:\n            if self.has_client_with_capability(goto_kind.lsp_name + \"Provider\"):\n                actions.append(\"<a href='{}'>{}</a>\".format(goto_kind.lsp_name, goto_kind.label))\n        if self.has_client_with_capability('referencesProvider'):\n            actions.append(\"<a href='{}'>{}</a>\".format('references', 'References'))\n        if self.has_client_with_capability('renameProvider'):\n            actions.append(\"<a href='{}'>{}</a>\".format('rename', 'Rename'))\n        return \"<p>\" + \" | \".join(actions) + \"</p>\"\n\n    def format_diagnostic_related_info(self, info: DiagnosticRelatedInformation) -> str:\n        file_path = info.location.file_path\n        if self._base_dir and file_path.startswith(self._base_dir):\n            file_path = os.path.relpath(file_path, self._base_dir)\n        location = \"{}:{}:{}\".format(file_path, info.location.range.start.row+1, info.location.range.start.col+1)\n        return \"<a href='location:{}'>{}</a>: {}\".format(location, location, escape(info.message))\n\n    def format_diagnostic(self, diagnostic: 'Diagnostic') -> str:\n        diagnostic_message = escape(diagnostic.message, False).replace('\\n', '<br>')\n        related_infos = [self.format_diagnostic_related_info(info) for info in diagnostic.related_info]\n        related_content = \"<pre class='related_info'>\" + \"<br>\".join(related_infos) + \"</pre>\" if related_infos else \"\"\n\n        if diagnostic.source:\n            return \"<pre class=\\\"{}\\\">[{}] {}{}</pre>\".format(class_for_severity[diagnostic.severity],\n                                                              diagnostic.source, diagnostic_message, related_content)\n        else:\n            return \"<pre class=\\\"{}\\\">{}{}</pre>\".format(class_for_severity[diagnostic.severity], diagnostic_message,\n                                                         related_content)\n\n    def diagnostics_content(self) -> str:\n        formatted = []\n        for config_name in self._diagnostics_by_config:\n            by_severity = {}  # type: Dict[int, List[str]]\n            formatted.append(\"<div class='diagnostics'>\")\n            for diagnostic in self._diagnostics_by_config[config_name]:\n                by_severity.setdefault(diagnostic.severity, []).append(self.format_diagnostic(diagnostic))\n\n            for severity, items in by_severity.items():\n                formatted.append(\"<div>\")\n                formatted.extend(items)\n                formatted.append(\"</div>\")\n\n            if config_name in self._actions_by_config:\n                action_count = len(self._actions_by_config[config_name])\n                if action_count > 0:\n                    formatted.append(\"<div class=\\\"actions\\\"><a href='{}:{}'>{} ({})</a></div>\".format(\n                        'code-actions', config_name, 'Code Actions', action_count))\n\n            formatted.append(\"</div>\")\n\n        return \"\".join(formatted)\n\n    def hover_content(self) -> str:\n        contents = []  # type: List[Any]\n        if isinstance(self._hover, dict):\n            response_content = self._hover.get('contents')\n            if response_content:\n                if isinstance(response_content, list):\n                    contents = response_content\n                else:\n                    contents = [response_content]\n\n        formatted = []\n        for item in contents:\n            value = \"\"\n            language = None\n            if isinstance(item, str):\n                value = item\n            else:\n                value = item.get(\"value\")\n                language = item.get(\"language\")\n\n            if '\\n' not in value:\n                value = \"\\n\".join(textwrap.wrap(value, 80))\n\n            if language:\n                formatted.append(\"```{}\\n{}\\n```\\n\".format(language, value))\n            else:\n                formatted.append(value)\n\n        if formatted:\n            return mdpopups.md2html(self.view, \"\\n\".join(formatted))\n\n        return \"\"\n\n    def request_show_hover(self, point: int) -> None:\n        sublime.set_timeout(lambda: self.show_hover(point), 50)\n\n    def show_hover(self, point: int) -> None:\n        contents = self.diagnostics_content() + self.hover_content()\n        if contents and settings.show_symbol_action_links:\n            contents += self.symbol_actions_content()\n\n        _test_contents.clear()\n        _test_contents.append(contents)  # for testing only\n\n        if contents:\n            mdpopups.show_popup(\n                self.view,\n                contents,\n                css=popups.stylesheet,\n                md=False,\n                flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,\n                location=point,\n                wrapper_class=popups.classname,\n                max_width=800,\n                on_navigate=lambda href: self.on_hover_navigate(href, point))\n\n    def on_hover_navigate(self, href: str, point: int) -> None:\n        for goto_kind in goto_kinds:\n            if href == goto_kind.lsp_name:\n                self.run_command_from_point(point, \"lsp_symbol_\" + goto_kind.subl_cmd_name)\n                return\n        if href == 'references':\n            self.run_command_from_point(point, \"lsp_symbol_references\")\n        elif href == 'rename':\n            self.run_command_from_point(point, \"lsp_symbol_rename\")\n        elif href.startswith('code-actions'):\n            _, config_name = href.split(\":\")\n            titles = [command[\"title\"] for command in self._actions_by_config[config_name]]\n            sel = self.view.sel()\n            sel.clear()\n            sel.add(sublime.Region(point, point))\n\n            self.view.show_popup_menu(titles, lambda i: self.handle_code_action_select(config_name, i))\n        elif href.startswith('location'):\n            _, file_path, location = href.split(\":\", 2)\n            file_path = os.path.join(self._base_dir, file_path) if self._base_dir else file_path\n            window = self.view.window()\n            if window:\n                window.open_file(file_path + \":\" + location, sublime.ENCODED_POSITION | sublime.TRANSIENT)\n        else:\n            webbrowser.open_new_tab(href)\n\n    def handle_code_action_select(self, config_name: str, index: int) -> None:\n        if index > -1:\n            selected = self._actions_by_config[config_name][index]\n            run_code_action_or_command(self.view, config_name, selected)\n\n    def run_command_from_point(self, point: int, command_name: str, args: Optional[Any] = None) -> None:\n        sel = self.view.sel()\n        sel.clear()\n        sel.add(sublime.Region(point, point))\n        self.view.run_command(command_name, args)\n", "path": "plugin/hover.py"}], "after_files": [{"content": "import mdpopups\nimport sublime\nimport sublime_plugin\nimport webbrowser\nimport os\nfrom html import escape\nfrom .code_actions import actions_manager, run_code_action_or_command\nfrom .code_actions import CodeActionOrCommand\nfrom .core.configurations import is_supported_syntax\nfrom .core.popups import popups\nfrom .core.protocol import Request, DiagnosticSeverity, Diagnostic, DiagnosticRelatedInformation, Point\nfrom .core.registry import session_for_view, LspTextCommand, windows\nfrom .core.settings import client_configs, settings\nfrom .core.typing import List, Optional, Any, Dict\nfrom .core.views import text_document_position_params\nfrom .diagnostics import filter_by_point, view_diagnostics\n\n\nSUBLIME_WORD_MASK = 515\n\n\nclass HoverHandler(sublime_plugin.ViewEventListener):\n    def __init__(self, view: sublime.View) -> None:\n        self.view = view\n\n    @classmethod\n    def is_applicable(cls, view_settings: dict) -> bool:\n        if 'hover' in settings.disabled_capabilities:\n            return False\n        syntax = view_settings.get('syntax')\n        if syntax:\n            return is_supported_syntax(syntax, client_configs.all)\n        else:\n            return False\n\n    def on_hover(self, point: int, hover_zone: int) -> None:\n        if hover_zone != sublime.HOVER_TEXT or self.view.is_popup_visible():\n            return\n        self.view.run_command(\"lsp_hover\", {\"point\": point})\n\n\n_test_contents = []  # type: List[str]\n\n\nclass_for_severity = {\n    DiagnosticSeverity.Error: 'errors',\n    DiagnosticSeverity.Warning: 'warnings',\n    DiagnosticSeverity.Information: 'info',\n    DiagnosticSeverity.Hint: 'hints'\n}\n\n\nclass GotoKind:\n\n    __slots__ = (\"lsp_name\", \"label\", \"subl_cmd_name\")\n\n    def __init__(self, lsp_name: str, label: str, subl_cmd_name: str) -> None:\n        self.lsp_name = lsp_name\n        self.label = label\n        self.subl_cmd_name = subl_cmd_name\n\n\ngoto_kinds = [\n    GotoKind(\"definition\", \"Definition\", \"definition\"),\n    GotoKind(\"typeDefinition\", \"Type Definition\", \"type_definition\"),\n    GotoKind(\"declaration\", \"Declaration\", \"declaration\"),\n    GotoKind(\"implementation\", \"Implementation\", \"implementation\")\n]\n\n\nclass LspHoverCommand(LspTextCommand):\n    def __init__(self, view: sublime.View) -> None:\n        super().__init__(view)\n        self._base_dir = None   # type: Optional[str]\n\n    def is_likely_at_symbol(self, point: int) -> bool:\n        word_at_sel = self.view.classify(point)\n        return bool(word_at_sel & SUBLIME_WORD_MASK)\n\n    def run(self, edit: sublime.Edit, point: Optional[int] = None) -> None:\n        hover_point = point or self.view.sel()[0].begin()\n        self._base_dir = windows.lookup(self.view.window()).get_project_path(self.view.file_name() or \"\")\n\n        self._hover = None  # type: Optional[Any]\n        self._actions_by_config = {}  # type: Dict[str, List[CodeActionOrCommand]]\n        self._diagnostics_by_config = {}  # type: Dict[str, List[Diagnostic]]\n\n        if self.is_likely_at_symbol(hover_point):\n            self.request_symbol_hover(hover_point)\n\n        self._diagnostics_by_config = filter_by_point(view_diagnostics(self.view),\n                                                      Point(*self.view.rowcol(hover_point)))\n        if self._diagnostics_by_config:\n            self.request_code_actions(hover_point)\n            self.request_show_hover(hover_point)\n\n    def request_symbol_hover(self, point: int) -> None:\n        # todo: session_for_view looks up windowmanager twice (config and for sessions)\n        # can we memoize some part (eg. where no point is provided?)\n        session = session_for_view(self.view, 'hoverProvider', point)\n        if session:\n            document_position = text_document_position_params(self.view, point)\n            if session.client:\n                session.client.send_request(\n                    Request.hover(document_position),\n                    lambda response: self.handle_response(response, point))\n\n    def request_code_actions(self, point: int) -> None:\n        actions_manager.request(self.view, point, lambda response: self.handle_code_actions(response, point),\n                                self._diagnostics_by_config)\n\n    def handle_code_actions(self, responses: Dict[str, List[CodeActionOrCommand]], point: int) -> None:\n        self._actions_by_config = responses\n        self.request_show_hover(point)\n\n    def handle_response(self, response: Optional[Any], point: int) -> None:\n        self._hover = response\n        self.request_show_hover(point)\n\n    def symbol_actions_content(self) -> str:\n        actions = []\n        for goto_kind in goto_kinds:\n            if self.has_client_with_capability(goto_kind.lsp_name + \"Provider\"):\n                actions.append(\"<a href='{}'>{}</a>\".format(goto_kind.lsp_name, goto_kind.label))\n        if self.has_client_with_capability('referencesProvider'):\n            actions.append(\"<a href='{}'>{}</a>\".format('references', 'References'))\n        if self.has_client_with_capability('renameProvider'):\n            actions.append(\"<a href='{}'>{}</a>\".format('rename', 'Rename'))\n        return \"<p>\" + \" | \".join(actions) + \"</p>\"\n\n    def format_diagnostic_related_info(self, info: DiagnosticRelatedInformation) -> str:\n        file_path = info.location.file_path\n        if self._base_dir and file_path.startswith(self._base_dir):\n            file_path = os.path.relpath(file_path, self._base_dir)\n        location = \"{}:{}:{}\".format(file_path, info.location.range.start.row+1, info.location.range.start.col+1)\n        return \"<a href='location:{}'>{}</a>: {}\".format(location, location, escape(info.message))\n\n    def format_diagnostic(self, diagnostic: 'Diagnostic') -> str:\n        diagnostic_message = escape(diagnostic.message, False).replace('\\n', '<br>')\n        related_infos = [self.format_diagnostic_related_info(info) for info in diagnostic.related_info]\n        related_content = \"<pre class='related_info'>\" + \"<br>\".join(related_infos) + \"</pre>\" if related_infos else \"\"\n\n        if diagnostic.source:\n            return \"<pre class=\\\"{}\\\">[{}] {}{}</pre>\".format(class_for_severity[diagnostic.severity],\n                                                              diagnostic.source, diagnostic_message, related_content)\n        else:\n            return \"<pre class=\\\"{}\\\">{}{}</pre>\".format(class_for_severity[diagnostic.severity], diagnostic_message,\n                                                         related_content)\n\n    def diagnostics_content(self) -> str:\n        formatted = []\n        for config_name in self._diagnostics_by_config:\n            by_severity = {}  # type: Dict[int, List[str]]\n            formatted.append(\"<div class='diagnostics'>\")\n            for diagnostic in self._diagnostics_by_config[config_name]:\n                by_severity.setdefault(diagnostic.severity, []).append(self.format_diagnostic(diagnostic))\n\n            for severity, items in by_severity.items():\n                formatted.append(\"<div>\")\n                formatted.extend(items)\n                formatted.append(\"</div>\")\n\n            if config_name in self._actions_by_config:\n                action_count = len(self._actions_by_config[config_name])\n                if action_count > 0:\n                    formatted.append(\"<div class=\\\"actions\\\"><a href='{}:{}'>{} ({})</a></div>\".format(\n                        'code-actions', config_name, 'Code Actions', action_count))\n\n            formatted.append(\"</div>\")\n\n        return \"\".join(formatted)\n\n    def hover_content(self) -> str:\n        contents = []  # type: List[Any]\n        if isinstance(self._hover, dict):\n            response_content = self._hover.get('contents')\n            if response_content:\n                if isinstance(response_content, list):\n                    contents = response_content\n                else:\n                    contents = [response_content]\n\n        formatted = []\n        for item in contents:\n            value = \"\"\n            language = None\n            if isinstance(item, str):\n                value = item\n            else:\n                value = item.get(\"value\")\n                language = item.get(\"language\")\n\n            if language:\n                formatted.append(\"```{}\\n{}\\n```\\n\".format(language, value))\n            else:\n                formatted.append(value)\n\n        if formatted:\n            frontmatter_config = mdpopups.format_frontmatter({'allow_code_wrap': True})\n            return mdpopups.md2html(self.view, frontmatter_config + \"\\n\".join(formatted))\n\n        return \"\"\n\n    def request_show_hover(self, point: int) -> None:\n        sublime.set_timeout(lambda: self.show_hover(point), 50)\n\n    def show_hover(self, point: int) -> None:\n        contents = self.diagnostics_content() + self.hover_content()\n        if contents and settings.show_symbol_action_links:\n            contents += self.symbol_actions_content()\n\n        _test_contents.clear()\n        _test_contents.append(contents)  # for testing only\n\n        if contents:\n            mdpopups.show_popup(\n                self.view,\n                contents,\n                css=popups.stylesheet,\n                md=False,\n                flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,\n                location=point,\n                wrapper_class=popups.classname,\n                max_width=800,\n                on_navigate=lambda href: self.on_hover_navigate(href, point))\n\n    def on_hover_navigate(self, href: str, point: int) -> None:\n        for goto_kind in goto_kinds:\n            if href == goto_kind.lsp_name:\n                self.run_command_from_point(point, \"lsp_symbol_\" + goto_kind.subl_cmd_name)\n                return\n        if href == 'references':\n            self.run_command_from_point(point, \"lsp_symbol_references\")\n        elif href == 'rename':\n            self.run_command_from_point(point, \"lsp_symbol_rename\")\n        elif href.startswith('code-actions'):\n            _, config_name = href.split(\":\")\n            titles = [command[\"title\"] for command in self._actions_by_config[config_name]]\n            sel = self.view.sel()\n            sel.clear()\n            sel.add(sublime.Region(point, point))\n\n            self.view.show_popup_menu(titles, lambda i: self.handle_code_action_select(config_name, i))\n        elif href.startswith('location'):\n            _, file_path, location = href.split(\":\", 2)\n            file_path = os.path.join(self._base_dir, file_path) if self._base_dir else file_path\n            window = self.view.window()\n            if window:\n                window.open_file(file_path + \":\" + location, sublime.ENCODED_POSITION | sublime.TRANSIENT)\n        else:\n            webbrowser.open_new_tab(href)\n\n    def handle_code_action_select(self, config_name: str, index: int) -> None:\n        if index > -1:\n            selected = self._actions_by_config[config_name][index]\n            run_code_action_or_command(self.view, config_name, selected)\n\n    def run_command_from_point(self, point: int, command_name: str, args: Optional[Any] = None) -> None:\n        sel = self.view.sel()\n        sel.clear()\n        sel.add(sublime.Region(point, point))\n        self.view.run_command(command_name, args)\n", "path": "plugin/hover.py"}]}