Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Server logs to panel #811

Merged
merged 71 commits into from Dec 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
35c587c
Implement a general-purpose panel toggler commmand
rwols Dec 2, 2019
13681ce
Replace 'lsp_show_diagnostics_panel' with 'lsp_toggle_panel'
rwols Dec 2, 2019
5c0a981
Working towards logging to a panel
rwols Dec 2, 2019
7b33477
Add sublime_lib dependency
rwols Dec 2, 2019
2211232
First steps with sublime_lib
rwols Dec 2, 2019
e0e67ca
Use an OutputPanel from sublime_lib to print server messages to the p…
rwols Dec 2, 2019
963e95e
Force writes, seek cursor to end before writing logs
rwols Dec 2, 2019
d539380
Convert the panel handling in references.py to using an OutputPanel
rwols Dec 2, 2019
558f489
Convert te panel handling in diagnostics.py to using a sublime_lib.Ou…
rwols Dec 2, 2019
7f4b8c8
Remove unused import
rwols Dec 2, 2019
2162c1e
All our panels are read-only
rwols Dec 2, 2019
5cb71ff
Don't forget to destroy the server log panel when the plugin is disabled
rwols Dec 2, 2019
7b83acf
Remove LspClearPanelCommand
rwols Dec 2, 2019
c8867c4
Remove LspUpdatePanelCommand
rwols Dec 2, 2019
18e03ab
Remove the server_log function
rwols Dec 2, 2019
1ffbde1
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 4, 2019
9621225
Fix error invoking log_callback during merge
rwols Dec 4, 2019
91ad2c7
Rework lsp_toggle_panel command
rwols Dec 4, 2019
a401798
Revert "Convert te panel handling in diagnostics.py to using a sublim…
rwols Dec 4, 2019
0dff79e
Revert "Convert the panel handling in references.py to using an Outpu…
rwols Dec 4, 2019
e4c6675
Revert "Remove LspUpdatePanelCommand"
rwols Dec 4, 2019
2b1503f
Revert "Remove LspClearPanelCommand"
rwols Dec 4, 2019
85c566e
Replace OutputPanel with lsp_update_server_panel command
rwols Dec 4, 2019
c7a53e2
Print LSP payloads to the server panel
rwols Dec 5, 2019
2b84d05
Align notifications with the other payload types ('<-- ' vs. '<--')
rwols Dec 5, 2019
bb01fea
Syntax highlight the server logs panel
rwols Dec 6, 2019
048042b
Do not print the payloads of textDocument/did{Change,Open}
rwols Dec 6, 2019
838606d
Revert "First steps with sublime_lib"
rwols Dec 6, 2019
41ea96b
Fix mypy errors
rwols Dec 6, 2019
0119948
Revert dependencies.json
rwols Dec 6, 2019
01aa8fe
Add a test for the circular behavior of the server log panel
rwols Dec 6, 2019
0316b51
Enable word-wrap for server logs
rwols Dec 6, 2019
465c123
Install the stderr log callback through the "session starter" callable
rwols Dec 6, 2019
361aa3e
Do not enable "word_wrap" for now
rwols Dec 6, 2019
c1caa9c
Fine tuning
rwols Dec 6, 2019
809b783
Use MockSettings in the pytest tests
rwols Dec 7, 2019
5b3ff2d
Wrong import location for ensure_server_panel in the test
rwols Dec 7, 2019
b93b710
Oops, accidentally disabled all debug logging. It is restored now
rwols Dec 7, 2019
2322d85
Also print unhandled notifications/requests to the server panel
rwols Dec 7, 2019
85801d2
Update LSP.sublime-settings
rwols Dec 7, 2019
b5f1d83
Fix mock Client class
rwols Dec 7, 2019
3e08a77
Fix sync requests not working for the server panel
rwols Dec 7, 2019
9f15d95
Remove #noqa line, used to be too long but not anymore
rwols Dec 7, 2019
5a87afb
Fix broken test depending on external state
rwols Dec 7, 2019
e3ad7d6
Deprecate lsp_show_diagnostics_panel command
rwols Dec 9, 2019
32aad5d
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 9, 2019
144dd48
Rename panel to "Language Servers" instead of "Server"
rwols Dec 9, 2019
aabcc73
Less monkey-typing, more functions for test_server_panel_circular.py
rwols Dec 9, 2019
45f738b
Put the name of the server after the arrow
rwols Dec 10, 2019
e096ffb
Remove the intro message, it seems a bit redundant
rwols Dec 10, 2019
24934a6
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 10, 2019
4cb2a41
Also account for payload results that are lists, and payload results …
rwols Dec 12, 2019
69e4050
Lookahead for any non-whitespace character instead of a '{'
rwols Dec 12, 2019
241e8d8
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 13, 2019
9eef111
Cleanly destroy panels
rwols Dec 14, 2019
a678863
Merge branch 'feature/server-logs-to-panel' of github.com:tomv564/LSP…
rwols Dec 14, 2019
cf70d00
Put "lsp_active": True in all panels
rwols Dec 14, 2019
fb1cd3c
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 17, 2019
9ae3f3e
Don't modify settings.py
rwols Dec 17, 2019
cbe8c6c
Minimally modify boot.py
rwols Dec 17, 2019
11b5452
Compactify imports
rwols Dec 17, 2019
fe5f2b8
Remove debug printing trying to figure out how panels are unloaded
rwols Dec 17, 2019
86fb529
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 18, 2019
b9eccf4
Don't make the WindowManager do all the work that the Client already did
rwols Dec 18, 2019
c6dd8b5
Just remove the Payload type entirely and replace with Any
rwols Dec 18, 2019
b77efa3
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 19, 2019
f9c990d
Just write two separate commands for the panel togglers
rwols Dec 19, 2019
178295c
Fix overindentation
rwols Dec 19, 2019
a9f385d
Ensure an int for request_id in rpc.py, it might be a string!
rwols Dec 19, 2019
384f3a3
Merge branch 'master' into feature/server-logs-to-panel
rwols Dec 21, 2019
062f571
struck by flakiness yet again
rwols Dec 21, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
9 changes: 6 additions & 3 deletions Commands/Default.sublime-commands
Expand Up @@ -60,9 +60,12 @@
"args": {}
},
{
"caption": "LSP: Show Diagnostics",
"command": "lsp_show_diagnostics_panel",
rwols marked this conversation as resolved.
Show resolved Hide resolved
"args": {}
"caption": "LSP: Toggle Panel: Language Servers",
"command": "lsp_toggle_server_panel",
},
{
"caption": "LSP: Toggle Panel: Diagnostics",
"command": "lsp_show_diagnostics_panel"
},
{
"caption": "LSP: Clear Diagnostics",
Expand Down
5 changes: 4 additions & 1 deletion Keymaps/Default (Linux).sublime-keymap
Expand Up @@ -13,7 +13,10 @@
{ "keys": ["ctrl+."], "command": "lsp_code_actions", "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Diagnostics Panel
{ "keys": ["ctrl+alt+m"], "command": "lsp_show_diagnostics_panel", "context": [{"key": "setting.lsp_active"}]},
{ "keys": ["ctrl+alt+m"], "command": "lsp_toggle_panel", "args": {"panel_type": "diagnostics"}, "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Language Server Logs Panel
// { "keys": ["UNBOUND"], "command": "lsp_toggle_panel", "args": {"panel_type": "language servers"}, "context": [{"key": "setting.lsp_active"}]},

// Trigger Signature Help
{ "keys": ["ctrl+alt+space"], "command": "noop", "context": [{ "key": "lsp.signature_help", "operator": "equal", "operand": 0}] },
Expand Down
5 changes: 4 additions & 1 deletion Keymaps/Default (OSX).sublime-keymap
Expand Up @@ -13,7 +13,10 @@
{ "keys": ["super+."], "command": "lsp_code_actions", "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Diagnostics Panel
{ "keys": ["super+alt+m"], "command": "lsp_show_diagnostics_panel", "context": [{"key": "setting.lsp_active"}]},
{ "keys": ["super+alt+m"], "command": "lsp_toggle_panel", "args": {"panel_type": "diagnostics"}, "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Language Server Logs Panel
// { "keys": ["UNBOUND"], "command": "lsp_toggle_panel", "args": {"panel_type": "language servers"}, "context": [{"key": "setting.lsp_active"}]},

// Trigger Signature Help
{ "keys": ["super+alt+space"], "command": "noop", "context": [{ "key": "lsp.signature_help", "operator": "equal", "operand": 0}] },
Expand Down
5 changes: 4 additions & 1 deletion Keymaps/Default (Windows).sublime-keymap
Expand Up @@ -13,7 +13,10 @@
{ "keys": ["ctrl+."], "command": "lsp_code_actions", "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Diagnostics Panel
{ "keys": ["ctrl+alt+m"], "command": "lsp_show_diagnostics_panel", "context": [{"key": "setting.lsp_active"}]},
{ "keys": ["ctrl+alt+m"], "command": "lsp_toggle_panel", "args": {"panel_type": "diagnostics"}, "context": [{"key": "setting.lsp_active"}]},

// Show/Hide Language Server Logs Panel
// { "keys": ["UNBOUND"], "command": "lsp_toggle_panel", "args": {"panel_type": "language servers"}, "context": [{"key": "setting.lsp_active"}]},

// Trigger Signature Help
{ "keys": ["ctrl+alt+space"], "command": "noop", "context": [{ "key": "lsp.signature_help", "operator": "equal", "operand": 0}] },
Expand Down
14 changes: 11 additions & 3 deletions LSP.sublime-settings
Expand Up @@ -82,13 +82,21 @@
// Show verbose debug messages in the sublime console.
"log_debug": false,

// Show notifications from language servers in the console.
// Show messages from language servers in the Language Servers output panel.
// This output panel can be toggled from the command palette with the
// command "LSP: Toggle Panel: Language Servers".
"log_server": true,

// Show language server stderr output in the console.
// Show language server stderr output in the Language Servers output panel.
// This output panel can be toggled from the command palette with the
// command "LSP: Toggle Panel: Language Servers".
"log_stderr": false,

// Show full JSON-RPC responses in the console
// Show full JSON-RPC requests/responses/notifications in the Language Servers
// output panel. Note that if the payload is very large, SublimeText will not
// highlight the log line.
// This output panel can be toggled from the command palette with the
// command "LSP: Toggle Panel: Language Servers".
"log_payloads": false,

// User clients configuration can be used to
Expand Down
92 changes: 92 additions & 0 deletions Syntaxes/ServerLog.sublime-syntax
@@ -0,0 +1,92 @@
%YAML 1.2
---
# [Subl]: https://www.sublimetext.com/docs/3/syntax.html
# [LSP]: https://github.com/Microsoft/language-server-protocol/blob/master/protocol.md
hidden: true
scope: output.lsp.log

variables:
method: '[[:alpha:]][[:alnum:]/]*'
servername: '[[:alnum:]_-]+'

contexts:
main:
- match: ^({{servername}})(:)
captures:
1: variable.function.lsp
2: punctuation.separator.lsp
push:
- meta_scope: meta.block.lsp
- match: $
pop: true
- match: '^::'
scope: punctuation.accessor.lsp
push:
- - meta_scope: meta.group.lsp
- match: $
pop: true
# responses
- - match: \d+
scope: constant.numeric.integer.decimal.lsp
set:
- match: ':'
scope: punctuation.separator.lsp
set: maybe-payload
- match: ''
pop: true
# notifications or requests
- match: (?=\w)
set:
# requests
- - match: \(
scope: punctuation.section.parens.begin.lsp
set:
- match: \d+
scope: constant.numeric.integer.decimal.lsp
set:
- match: \)
scope: punctuation.section.parens.end.lsp
set:
- match: ':'
scope: punctuation.separator.lsp
set: maybe-payload
- match: ''
pop: true
# notifications
- match: ':'
scope: punctuation.separator.lsp
set: maybe-payload
- match: ''
pop: true
- - match: '{{method}}'
scope: keyword.control.lsp
pop: true
# language server name
- - match: \S+
scope: variable.function.lsp
pop: true
# arrows
- - match: -->
scope: storage.modifier.lsp
pop: true
- match: <--
scope: storage.modifier.lsp
pop: true
- match: ==>
scope: storage.modifier.lsp
pop: true
- match: unhandled
scope: invalid.deprecated.lsp
pop: true

maybe-payload:
- match: \s*(?=\S)
set:
- match: $
pop: true
- include: scope:source.python#constants # e.g. shutdown request
- include: scope:source.python#lists
- include: scope:source.python#dictionaries-and-sets
- match: ''
pop: true
...
1 change: 1 addition & 0 deletions boot.py
Expand Up @@ -4,6 +4,7 @@
from .plugin.core.panels import *
from .plugin.core.registry import LspRestartClientCommand
from .plugin.core.documents import *
from .plugin.panels import *
from .plugin.edit import *
from .plugin.completion import *
from .plugin.diagnostics import *
Expand Down
2 changes: 1 addition & 1 deletion dependencies.json
Expand Up @@ -10,4 +10,4 @@
"pyyaml"
]
}
}
}
6 changes: 4 additions & 2 deletions plugin/core/clients.py
Expand Up @@ -42,7 +42,8 @@ def start_window_config(window: sublime.Window,
config: ClientConfig,
on_pre_initialize: 'Callable[[Session], None]',
on_post_initialize: 'Callable[[Session], None]',
on_post_exit: 'Callable[[str], None]') -> 'Optional[Session]':
on_post_exit: 'Callable[[str], None]',
on_stderr_log: 'Optional[Callable[[str], None]]') -> 'Optional[Session]':
args, env = get_window_env(window, config)
config.binary_args = args
return create_session(config=config,
Expand All @@ -51,7 +52,8 @@ def start_window_config(window: sublime.Window,
settings=settings,
on_pre_initialize=on_pre_initialize,
on_post_initialize=on_post_initialize,
on_post_exit=lambda config_name: on_session_ended(window, config_name, on_post_exit))
on_post_exit=lambda config_name: on_session_ended(window, config_name, on_post_exit),
on_stderr_log=on_stderr_log)


def on_session_ended(window: sublime.Window, config_name: str, on_post_exit_handler: 'Callable[[str], None]') -> None:
Expand Down
11 changes: 0 additions & 11 deletions plugin/core/logging.py
Expand Up @@ -8,7 +8,6 @@

log_debug = False
log_exceptions = True
log_server = True


def set_debug_logging(logging_enabled: bool) -> None:
Expand All @@ -21,11 +20,6 @@ def set_exception_logging(logging_enabled: bool) -> None:
log_exceptions = logging_enabled


def set_server_logging(logging_enabled: bool) -> None:
global log_server
log_server = logging_enabled


def debug(*args: 'Any') -> None:
"""Print args to the console if the "debug" setting is True."""
if log_debug:
Expand All @@ -39,11 +33,6 @@ def exception_log(message: str, ex: Exception) -> None:
print(''.join(traceback.format_exception(ex.__class__, ex, ex_traceback)))


def server_log(server_name: str, *args: 'Any') -> None:
if log_server:
printf(*args, prefix=server_name)


def printf(*args: 'Any', prefix: str = 'LSP') -> None:
"""Print args to the console, prefixed by the plugin name."""
print(prefix + ":", *args)
20 changes: 13 additions & 7 deletions plugin/core/main.py
@@ -1,13 +1,13 @@
import sublime

from .settings import settings, load_settings, unload_settings
from .logging import set_debug_logging, set_server_logging
from .registry import windows, load_handlers, unload_sessions
from .panels import destroy_output_panels
from .logging import set_debug_logging, set_exception_logging
from .panels import destroy_output_panels, ensure_panel, PanelName
from .popups import popups
from .registry import windows, load_handlers, unload_sessions
from .settings import settings, load_settings, unload_settings
from ..color import remove_color_boxes
from ..diagnostics import DiagnosticsPresenter
from ..highlights import remove_highlights
from ..color import remove_color_boxes

try:
from typing import Any, List, Dict, Tuple, Callable, Optional, Set
Expand All @@ -16,12 +16,18 @@
pass


def ensure_server_panel(window: sublime.Window) -> 'Optional[sublime.View]':
return ensure_panel(window, PanelName.LanguageServers, "", "", "Packages/LSP/Syntaxes/ServerLog.sublime-syntax")


def startup() -> None:
load_settings()
set_debug_logging(settings.log_debug)
set_server_logging(settings.log_server)
popups.load_css()
set_debug_logging(settings.log_debug)
set_exception_logging(True)
windows.set_diagnostics_ui(DiagnosticsPresenter)
windows.set_server_panel_factory(ensure_server_panel)
windows.set_settings_factory(settings)
load_handlers()
sublime.status_message("LSP initialized")
start_active_window()
Expand Down
65 changes: 54 additions & 11 deletions plugin/core/panels.py
@@ -1,30 +1,50 @@
from contextlib import contextmanager
import sublime
import sublime_plugin

try:
from typing import Optional, Any
assert Optional, Any
from typing import Optional, Any, List, Generator
assert Optional and Any and List and Generator
except ImportError:
pass


# about 80 chars per line implies maintaining a buffer of about 40kb per window
SERVER_PANEL_MAX_LINES = 500


OUTPUT_PANEL_SETTINGS = {
"auto_indent": False,
"draw_indent_guides": False,
"draw_white_space": "None",
"fold_buttons": True,
"gutter": True,
'is_widget': True,
"is_widget": True,
"line_numbers": False,
"lsp_active": True,
"margin": 3,
"match_brackets": False,
"rulers": [],
"scroll_past_end": False,
"tab_size": 4,
"translate_tabs_to_spaces": False,
"word_wrap": False,
"fold_buttons": True
"word_wrap": False
}


class PanelName:
Diagnostics = "diagnostics"
References = "references"
LanguageServers = "language servers"


@contextmanager
def mutable(view: sublime.View) -> 'Generator':
view.set_read_only(False)
yield
view.set_read_only(True)


def create_output_panel(window: sublime.Window, name: str) -> 'Optional[sublime.View]':
panel = window.create_output_panel(name)
settings = panel.settings()
Expand All @@ -34,8 +54,12 @@ def create_output_panel(window: sublime.Window, name: str) -> 'Optional[sublime.


def destroy_output_panels(window: sublime.Window) -> None:
for panel_name in ["references", "diagnostics"]:
window.destroy_output_panel(panel_name)
for field in filter(lambda a: not a.startswith('__'), PanelName.__dict__.keys()):
panel_name = getattr(PanelName, field)
panel = window.find_output_panel(panel_name)
if panel and panel.is_valid():
panel.settings().set("syntax", "Packages/Text/Plain text.tmLanguage")
window.destroy_output_panel(panel_name)


def create_panel(window: sublime.Window, name: str, result_file_regex: str, result_line_regex: str,
Expand All @@ -50,6 +74,8 @@ def create_panel(window: sublime.Window, name: str, result_file_regex: str, resu
# settings, so that it'll be picked up as a result buffer
# see: Packages/Default/exec.py#L228-L230
panel = window.create_output_panel(name)
# All our panels are read-only
panel.set_read_only(True)
return panel


Expand All @@ -64,9 +90,8 @@ class LspClearPanelCommand(sublime_plugin.TextCommand):
"""

def run(self, edit: sublime.Edit) -> None:
self.view.set_read_only(False)
self.view.erase(edit, sublime.Region(0, self.view.size()))
self.view.set_read_only(True)
with mutable(self.view):
self.view.erase(edit, sublime.Region(0, self.view.size()))


class LspUpdatePanelCommand(sublime_plugin.TextCommand):
Expand All @@ -78,8 +103,26 @@ def run(self, edit: sublime.Edit, characters: 'Optional[str]' = "") -> None:
# Clear folds
self.view.unfold(sublime.Region(0, self.view.size()))

self.view.replace(edit, sublime.Region(0, self.view.size()), characters or "")
with mutable(self.view):
self.view.replace(edit, sublime.Region(0, self.view.size()), characters or "")

# Clear the selection
selection = self.view.sel()
selection.clear()


class LspUpdateServerPanelCommand(sublime_plugin.TextCommand):
def run(self, edit: sublime.Edit, prefix: str, message: str) -> None:
with mutable(self.view):
self.view.insert(edit, self.view.size(), "{}: {}\n".format(prefix, message))
total_lines, _ = self.view.rowcol(self.view.size())
point = 0 # Starting from point 0 in the panel ...
regions = [] # type: List[sublime.Region]
for _ in range(0, max(0, total_lines - SERVER_PANEL_MAX_LINES)):
tomv564 marked this conversation as resolved.
Show resolved Hide resolved
# ... collect all regions that span an entire line ...
region = self.view.full_line(point)
regions.append(region)
point = region.b
for region in reversed(regions):
# ... and erase them in reverse order
self.view.erase(edit, region)