Repository: sublimelsp/LSP

Issue:
Why there are scroll bars on the houver pop up with so much screen available for it?
When reporting the issue: 
1. https://github.com/palantir/python-language-server/issues/464 Go to definition has a annoying behavior sometimes

I noticed this:
![fsg](https://user-images.githubusercontent.com/5332158/50059436-eb2a6d00-016d-11e9-9cfb-e865ea3e1139.gif)

Are the scroll bars being put there by LSP or Sublime Text? If by LSP, would be nice a setting to extend their limits/maximum sizes. They do not seem big enough.
Signature Help height too short (need to scroll)
I am not sure if this is SublimeText or LSP. The popup cuts off after about two lines.

* Ubuntu, ccls
* Package Control or git (both do the same)
* Create a function with many long parameters.

![Screenshot from 2019-07-08 15-11-41](https://user-images.githubusercontent.com/16208294/60887754-6d3aca00-a255-11e9-83e6-3aff595c57eb.png)




Discussion:
LSP passes a `max_width` parameter to mdpopups's `show_popup` function.
Can you find a value that works for you use there?
I set 1200, now it show like this:
![image](https://user-images.githubusercontent.com/5332158/50386128-486f7280-06c8-11e9-8d9f-d6b5d5abd89c.png)

So, I would need to hard code this value? Could this be a setting or detected by screen size?
```python
File: Data/Packages/LSP/plugin/hover.py
147:     def show_hover(self, point, contents):
148:         mdpopups.show_popup(
149:             self.view,
150:             contents,
151:             css=popup_css,
152:             md=False,
153:             flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
154:             location=point,
155:             wrapper_class=popup_class,
156:             max_width=1200,
157:             on_navigate=lambda href: self.on_hover_navigate(href, point))
158: 
```
How does it behave if we don't specify a `max_width` ? It would be great to let Sublime make an informed decision about popup width!
1. If we do not specify a value `mdpopups` defaults to 320.
1. If `mdpopups` do not specify a value, the `sublime`'s view module also defaults to 320.

This could be either an enhancement for `sublime`'s view module or `mdpopups` dependency:
1. If we specify a wildcard value as -1 or 0, they should adjust the maximum width automatically.
1. Or we just set it to a big value like 2000 and `sublime`'s view module or `mdpopups` dependency should automatically not show it bigger than the user's screen maximum width, i.e., outside the screen.
Thanks for the in-depth investigations!

Normally the popup is vertically sized to accommodate the 3 lines of text. The horizontal scrollbar 
seems to be missing from this vertical size calculation. If it's not our CSS causing this, then we should report this to Sublime Core issues?

As for configuring `max_width`, I feel 800px is a reasonable maximum for pleasant reading of paragraphs of text. The real challenge is that long non-breakable URL :/

Open to suggestions for actions for LSP!
https://github.com/SublimeTextIssues/Core/issues/2711 is also a likely explanation. Two things we can try:

* Manually wrap long lines at X chars (say 80)
* Avoid having long content in `span` tags.
May be try to use something else other than `<span>` tags?
Being able to control the scroll position in the signature help would be an alternative to making it larger. The main issue with only seeing two lines is that each time you move to a new parameter the popup updates and scrolls back to the top.

For now, the following gives me something that is more useful for me:
```diff
diff --git a/plugin/signature_help.py b/plugin/signature_help.py
index e058a03..1d21407 100644
--- a/plugin/signature_help.py
+++ b/plugin/signature_help.py
@@ -40,7 +40,7 @@ class ColorSchemeScopeRenderer(object):
         color = self._scope_styles[scope]["color"]
         additional_styles = 'font-weight: bold; text-decoration: underline;' if emphasize else ''
         content = html.escape(content, quote=False) if escape else content
-        return '<span style="color: {};{}">{}</span>'.format(color, additional_styles, content)
+        return '<br><span style="color: {};{}">{}</span>'.format(color, additional_styles, content)
 
 
 class SignatureHelpListener(sublime_plugin.ViewEventListener):
@@ -129,7 +129,7 @@ class SignatureHelpListener(sublime_plugin.ViewEventListener):
                             content,
                             css=popup_css,
                             md=True,
-                            flags=sublime.HIDE_ON_MOUSE_MOVE_AWAY,
+                            flags=0,
                             location=point,
                             wrapper_class=popup_class,
                             max_width=800,
```
possible duplicate of #486
Closing duplicate, please follow the linked issue  for updates :)

Resolving patch:
diff --git a/plugin/core/signature_help.py b/plugin/core/signature_help.py
--- a/plugin/core/signature_help.py
+++ b/plugin/core/signature_help.py
@@ -141,11 +141,35 @@ def create_signature_help(response: 'Optional[Dict]') -> 'Optional[SignatureHelp
         return None
 
 
+def find_params_to_split_at(label: str) -> 'List[int]':
+    max_length = 80
+    params_to_newline_before = []  # type: List[int]
+    if len(label) > max_length and '\n' not in label:
+        param_index = 0
+        last_comma_offset = 0
+        line_offset = 0
+        while True:
+            comma_offset = label.find(',', last_comma_offset)
+            if comma_offset == -1:
+                if len(label) - line_offset > max_length:
+                    # If no more commas, but remainder is too long, add a split
+                    params_to_newline_before.append(param_index)
+                break
+            param_index += 1
+            if comma_offset - line_offset > max_length:
+                params_to_newline_before.append(param_index)
+                line_offset = last_comma_offset
+                if max_length == 80:
+                    max_length = 76  # account for 4-space indent.
+            last_comma_offset = comma_offset + 1
+    return params_to_newline_before
+
+
 def render_signature_label(renderer: ScopeRenderer, sig_info: SignatureInformation,
                            active_parameter_index: int = -1) -> str:
-
     if sig_info.parameters:
         label = sig_info.label
+        params_to_newline_before = find_params_to_split_at(label)
 
         # replace with styled spans in reverse order
 
@@ -155,12 +179,14 @@ def render_signature_label(renderer: ScopeRenderer, sig_info: SignatureInformati
             label = label[:start] + renderer.punctuation(label[start:end]) + html.escape(label[end:], quote=False)
 
         max_param_index = len(sig_info.parameters) - 1
-        for index, param in enumerate(reversed(sig_info.parameters)):
+        for reverse_index, param in enumerate(reversed(sig_info.parameters)):
             if param.range:
                 start, end = param.range
-                is_current = active_parameter_index == max_param_index - index
+                forward_index = max_param_index - reverse_index
+                is_current = active_parameter_index == forward_index
                 rendered_param = renderer.parameter(content=label[start:end], emphasize=is_current)
-                label = label[:start] + rendered_param + label[end:]
+                maybe_newline = "<br>&nbsp;&nbsp;&nbsp;&nbsp;" if forward_index in params_to_newline_before else ""
+                label = label[:start] + maybe_newline + rendered_param + label[end:]
 
                 # todo: highlight commas between parameters as punctuation.
 
diff --git a/plugin/hover.py b/plugin/hover.py
--- a/plugin/hover.py
+++ b/plugin/hover.py
@@ -3,6 +3,7 @@
 import sublime_plugin
 import webbrowser
 import os
+import textwrap
 from html import escape
 from .core.configurations import is_supported_syntax
 from .diagnostics import filter_by_point, view_diagnostics
@@ -198,6 +199,8 @@ def hover_content(self) -> str:
             if language:
                 formatted.append("```{}\n{}\n```\n".format(language, value))
             else:
+                if '\n' not in value:
+                    value = "\n".join(textwrap.wrap(value, 80))
                 formatted.append(value)
 
         if formatted:


Test patch:
diff --git a/plugin/core/test_signature_help.py b/plugin/core/test_signature_help.py
--- a/plugin/core/test_signature_help.py
+++ b/plugin/core/test_signature_help.py
@@ -234,6 +234,26 @@ def test_params_no_parens(self):
  \n<variable.parameter>foo</variable.parameter>\
  \n<variable.parameter emphasize>foo</variable.parameter></entity.name.function>""")
 
+    def test_long_signature(self):
+        # self.maxDiff = None
+        sig = create_signature(
+            """do_the_foo_bar_if_correct_with_optional_bar_and_uppercase_option(takes_a_mandatory_foo: int, \
+bar_if_needed: Optional[str], in_uppercase: Optional[bool]) -> Optional[str]""",
+            "takes_a_mandatory_foo",
+            "bar_if_needed",
+            "in_uppercase",
+            activeParameter=1)
+        help = create_signature_help(dict(signatures=[sig]))
+        if help:
+            label = render_signature_label(renderer, help.active_signature(), 1)
+            self.assertEqual(label, """
+<entity.name.function>do_the_foo_bar_if_correct_with_optional_bar_and_uppercase_option
+<punctuation>(</punctuation>
+<variable.parameter>takes_a_mandatory_foo</variable.parameter>: int,\
+ <br>&nbsp;&nbsp;&nbsp;&nbsp;\n<variable.parameter emphasize>bar_if_needed</variable.parameter>: Optional[str],\
+ <br>&nbsp;&nbsp;&nbsp;&nbsp;\n<variable.parameter>in_uppercase</variable.parameter>: Optional[bool]
+<punctuation>)</punctuation> -&gt; Optional[str]</entity.name.function>""")
+
 
 class SignatureHelpTests(unittest.TestCase):