Skip to content

Commit

Permalink
Never close the diags panel automatically, and more (#1525)
Browse files Browse the repository at this point in the history
Because the diags panel is never closed automatically, it makes little sense
to have it automatically open whenever there's an error/warning. So the
setting

    auto_show_diagnostics_panel

is removed. Instead

    auto_show_diagnostics_panel_level

is used to determine when to automatically open the panel *on save*. Put the
value `0` here to never open the panel.

I've also added a neutral "idle" message for when there are no diagnostics.
  • Loading branch information
rwols authored Dec 13, 2020
1 parent b879a25 commit 4ab9774
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 73 deletions.
14 changes: 5 additions & 9 deletions LSP.sublime-settings
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,7 @@
// Show permanent language server status in the status bar.
"show_view_status": true,

// Open and close the diagnostics panel automatically,
// depending on available diagnostics.
// Valid values are "never", "always" and "saved"
"auto_show_diagnostics_panel": "saved",

// Run the server's formatProvider (if supported) on a document before saving.
// Run the server's formatProvider (if supported) on a file before saving.
// This option is also supported in syntax-specific settings and/or in the
// "settings" section of project files.
"lsp_format_on_save": false,
Expand All @@ -32,8 +27,9 @@
// The amount of time the code actions on save are allowed to run for.
"code_action_on_save_timeout_ms": 2000,

// Open the diagnostics panel automatically
// when diagnostics level is equal to or less than:
// Open the diagnostics panel automatically on save when diagnostics level is
// equal to or less than:
// none: 0 (never open the panel automatically)
// error: 1
// warning: 2
// info: 3
Expand All @@ -49,7 +45,7 @@

// Show highlights and gutter markers in the file views for diagnostics
// with level equal to or less than:
// none: 0
// none: 0 (never show)
// error: 1
// warning: 2
// info: 3
Expand Down
2 changes: 2 additions & 0 deletions Syntaxes/Diagnostics.sublime-syntax
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ scope: output.lsp.diagnostics

contexts:
main:
- match: ^ No diagnostics. Well done!$
scope: comment.line.placeholder.lsp
- include: file
- include: line

Expand Down
4 changes: 0 additions & 4 deletions plugin/core/sessions.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,6 @@ def update_diagnostics_panel_async(self) -> None:
def show_diagnostics_panel_async(self) -> None:
pass

@abstractmethod
def hide_diagnostics_panel_async(self) -> None:
pass

# Event callbacks

@abstractmethod
Expand Down
16 changes: 4 additions & 12 deletions plugin/core/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,6 @@ def read_list_setting(settings_obj: sublime.Settings, key: str, default: list) -
class Settings:

# This is only for mypy
auto_show_diagnostics_panel = None # type: str
auto_show_diagnostics_panel_level = None # type: int
code_action_on_save_timeout_ms = None # type: int
diagnostics_additional_delay_auto_complete_ms = None # type: int
Expand Down Expand Up @@ -181,7 +180,6 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None:
val = s.get(name)
setattr(self, name, val if isinstance(val, default.__class__) else default)

# r("auto_show_diagnostics_panel", "always")
r("auto_show_diagnostics_panel_level", 2)
r("code_action_on_save_timeout_ms", 2000)
r("diagnostics_additional_delay_auto_complete_ms", 0)
Expand Down Expand Up @@ -219,11 +217,11 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None:
# Backwards-compatible with the bool setting
auto_show_diagnostics_panel = s.get("auto_show_diagnostics_panel")
if isinstance(auto_show_diagnostics_panel, bool):
self.auto_show_diagnostics_panel = "always" if auto_show_diagnostics_panel else "never"
if not auto_show_diagnostics_panel:
self.auto_show_diagnostics_panel_level = 0
elif isinstance(auto_show_diagnostics_panel, str):
self.auto_show_diagnostics_panel = auto_show_diagnostics_panel
else:
self.auto_show_diagnostics_panel = "always"
if auto_show_diagnostics_panel == "never":
self.auto_show_diagnostics_panel_level = 0

# Backwards-compatible with "only_show_lsp_completions"
only_show_lsp_completions = s.get("only_show_lsp_completions")
Expand All @@ -236,12 +234,6 @@ def r(name: str, default: Union[bool, int, str, list, dict]) -> None:

set_debug_logging(self.log_debug)

def show_diagnostics_panel_always(self) -> bool:
return self.auto_show_diagnostics_panel == "always"

def show_diagnostics_panel_on_save(self) -> bool:
return self.auto_show_diagnostics_panel == "saved"

def document_highlight_style_to_add_regions_flags(self) -> int:
return _settings_style_to_add_regions_flag(self.document_highlight_style)

Expand Down
62 changes: 29 additions & 33 deletions plugin/core/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
from .protocol import Diagnostic
from .protocol import Error
from .protocol import Point
from .sessions import get_plugin
from .sessions import Logger
from .sessions import Manager
from .sessions import Session
from .sessions import SessionBufferProtocol
from .sessions import get_plugin
from .sessions import SessionViewProtocol
from .settings import userprefs
from .transports import create_transport
Expand All @@ -35,12 +35,16 @@
from time import time
from weakref import ref
from weakref import WeakSet
import functools
import json
import os
import sublime
import threading


_NO_DIAGNOSTICS_PLACEHOLDER = " No diagnostics. Well done!"


class AbstractViewListener(metaclass=ABCMeta):

TOTAL_ERRORS_AND_WARNINGS_STATUS_KEY = "lsp_total_errors_and_warnings"
Expand Down Expand Up @@ -127,6 +131,7 @@ def __init__(
self._panel_code_phantoms = None # type: Optional[sublime.PhantomSet]
self.total_error_count = 0
self.total_warning_count = 0
sublime.set_timeout(functools.partial(self._update_panel_main_thread, None, _NO_DIAGNOSTICS_PLACEHOLDER, []))

def get_config_manager(self) -> WindowConfigManager:
return self._configs
Expand Down Expand Up @@ -437,42 +442,33 @@ def update_diagnostics_panel_async(self) -> None:
for listener in listeners:
set_diagnostics_count(listener.view, self.total_error_count, self.total_warning_count)
characters = "\n".join(to_render)

def update() -> None:
panel = ensure_diagnostics_panel(self._window)
if not panel or not panel.is_valid():
return
if isinstance(base_dir, str):
panel.settings().set("result_base_dir", base_dir)
else:
panel.settings().erase("result_base_dir")
panel.run_command("lsp_update_panel", {"characters": characters})
if self._panel_code_phantoms is None:
self._panel_code_phantoms = sublime.PhantomSet(panel, "hrefs")
phantoms = [] # type: List[sublime.Phantom]
for row, col, code, href in prephantoms:
point = panel.text_point(row, col)
region = sublime.Region(point, point)
phantoms.append(sublime.Phantom(region, make_link(href, code), sublime.LAYOUT_INLINE))
self._panel_code_phantoms.update(phantoms)

sublime.set_timeout(update)

def _can_manipulate_diagnostics_panel(self) -> bool:
active_panel = self._window.active_panel()
if active_panel is not None:
return active_panel == "output.diagnostics"
return True
if not characters:
characters = _NO_DIAGNOSTICS_PLACEHOLDER
sublime.set_timeout(functools.partial(self._update_panel_main_thread, base_dir, characters, prephantoms))

def _update_panel_main_thread(self, base_dir: Optional[str], characters: str,
prephantoms: List[Tuple[int, int, str, str]]) -> None:
panel = ensure_diagnostics_panel(self._window)
if not panel or not panel.is_valid():
return
if isinstance(base_dir, str):
panel.settings().set("result_base_dir", base_dir)
else:
panel.settings().erase("result_base_dir")
panel.run_command("lsp_update_panel", {"characters": characters})
if self._panel_code_phantoms is None:
self._panel_code_phantoms = sublime.PhantomSet(panel, "hrefs")
phantoms = [] # type: List[sublime.Phantom]
for row, col, code, href in prephantoms:
point = panel.text_point(row, col)
region = sublime.Region(point, point)
phantoms.append(sublime.Phantom(region, make_link(href, code), sublime.LAYOUT_INLINE))
self._panel_code_phantoms.update(phantoms)

def show_diagnostics_panel_async(self) -> None:
if self._can_manipulate_diagnostics_panel():
if self._window.active_panel() is None:
self._window.run_command("show_panel", {"panel": "output.diagnostics"})

def hide_diagnostics_panel_async(self) -> None:
# prevent flickering on-save
if self._can_manipulate_diagnostics_panel() and userprefs().auto_show_diagnostics_panel != "saved":
self._window.run_command("hide_panel", {"panel": "output.diagnostics"})

def select_next_diagnostic_async(self) -> None:
self._select_diagnostic_async(1)

Expand Down
13 changes: 4 additions & 9 deletions plugin/session_buffer.py
Original file line number Diff line number Diff line change
Expand Up @@ -229,11 +229,10 @@ def on_post_save_async(self, view: sublime.View) -> None:
self.purge_changes_async(view)
# mypy: expected sublime.View, got ViewLike
self.session.send_notification(did_save(view, include_text, self.file_name))
if userprefs().show_diagnostics_panel_on_save():
if self.should_show_diagnostics_panel:
mgr = self.session.manager()
if mgr:
mgr.show_diagnostics_panel_async()
if self.should_show_diagnostics_panel:
mgr = self.session.manager()
if mgr:
mgr.show_diagnostics_panel_async()

def some_view(self) -> Optional[sublime.View]:
for sv in self.session_views:
Expand Down Expand Up @@ -346,10 +345,6 @@ def _present_diagnostics_async(
mgr = self.session.manager()
if mgr:
mgr.update_diagnostics_panel_async()
if not self.should_show_diagnostics_panel:
mgr.hide_diagnostics_panel_async()
elif userprefs().show_diagnostics_panel_always():
mgr.show_diagnostics_panel_async()

def __str__(self) -> str:
return '{}:{}:{}'.format(self.session.config.name, self.id, self.file_name)
6 changes: 3 additions & 3 deletions sublime-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@
}
],
"default": "saved",
"markdownDescription": "Open and close the diagnostics panel automatically, depending on available diagnostics. For backward-compatibility, this can also be a boolean. In that case, if set to `false`, don't show the diagnostics panel, and when set to `true`, always show the diagnostics panel."
"deprecationMessage": "Use the \"auto_show_diagnostics_panel_level\" setting instead."
},
"code_action_on_save_timeout_ms": {
"type": "integer",
Expand All @@ -182,10 +182,10 @@
},
"auto_show_diagnostics_panel_level": {
"type": "integer",
"minimum": 1,
"minimum": 0,
"maximum": 4,
"default": 2,
"markdownDescription": "Open the diagnostics panel automatically when diagnostics level is equal to or less than:\n\n- _error_: `1`,\n- _warning_: `2`,\n- _info_: `3`,\n- _hint_: `4`"
"markdownDescription": "Open the diagnostics panel automatically **on save** when diagnostics level is equal to or less than:\n\n- _none_: `0` (this means never show the panel automatically),\n- _error_: `1`,\n- _warning_: `2`,\n- _info_: `3`,\n- _hint_: `4`\n\nThe panel is not shown when there is already another panel open. The panel is never _closed_ automatically. To close the panel, press the <kbd>Esc</kbd> key."
},
"show_diagnostics_count_in_view_status": {
"type": "boolean",
Expand Down
3 changes: 0 additions & 3 deletions tests/test_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,6 @@ def update_diagnostics_panel_async(self) -> None:
def show_diagnostics_panel_async(self) -> None:
pass

def hide_diagnostics_panel_async(self) -> None:
pass


class MockLogger(Logger):

Expand Down

0 comments on commit 4ab9774

Please sign in to comment.