diff --git a/modules/adapters/lldb.py b/modules/adapters/lldb.py index 95e4cc0f..90665041 100644 --- a/modules/adapters/lldb.py +++ b/modules/adapters/lldb.py @@ -39,7 +39,7 @@ def _read(self, file: Any, callback: Callable[[str], None]) -> None: core.info(line) core.call_soon_threadsafe(callback, line) except Exception as e: - core.log_exception() + core.exception() break def dispose(self) -> None: diff --git a/modules/adapters/util/dependencies.py b/modules/adapters/util/dependencies.py index 2169bddd..7817d381 100644 --- a/modules/adapters/util/dependencies.py +++ b/modules/adapters/util/dependencies.py @@ -7,7 +7,6 @@ import shutil def version_tuple(v): - print(v) return tuple(v.split('.')) def get_node_path(adapter_type: str) -> str: diff --git a/modules/breakpoints/__init__.py b/modules/breakpoints/__init__.py index ff399990..6d09b87b 100644 --- a/modules/breakpoints/__init__.py +++ b/modules/breakpoints/__init__.py @@ -1,6 +1,5 @@ from __future__ import annotations from ..typecheck import * -from ..import core from ..import ui from .. import dap diff --git a/modules/output_view.py b/modules/console_output_view.py similarity index 97% rename from modules/output_view.py rename to modules/console_output_view.py index 996f2dc0..ec8b0c9d 100644 --- a/modules/output_view.py +++ b/modules/console_output_view.py @@ -3,10 +3,8 @@ from .console_view import ConsoleView from .import core -from .import ui from .settings import Settings -import re import sublime import sublime_plugin @@ -40,7 +38,7 @@ def _window_has_output_views(window: sublime.Window): return False -class OutputView(ConsoleView): +class ConsoleOutputView(ConsoleView): def __init__(self, window: sublime.Window, name: str, on_close: Callable[[], None]|None = None): DebuggerPreConsoleWindowHooks(window).run() diff --git a/modules/core/__init__.py b/modules/core/__init__.py index 52af08cd..abe15958 100644 --- a/modules/core/__init__.py +++ b/modules/core/__init__.py @@ -5,13 +5,14 @@ from .core import * from .sublime import * -from .log import * from .event import Handle, Event, EventReturning from . import platform from .error import Error from .json import json_encode, json_decode +from .log import * + _current_package = __package__.split('.', 1)[0] _current_package_path = os.path.join(sublime.packages_path(), _current_package) diff --git a/modules/core/core.py b/modules/core/core.py index 44753d2a..d9fde302 100644 --- a/modules/core/core.py +++ b/modules/core/core.py @@ -5,7 +5,7 @@ import concurrent import asyncio -from .log import log_exception +from .log import exception from .sublime_event_loop import SublimeEventLoop T = TypeVar('T') @@ -72,7 +72,7 @@ def done(task: asyncio.Future[T]) -> None: try: raise exception except Exception as e: - log_exception() + exception() return diff --git a/modules/core/json.py b/modules/core/json.py index 7890ec75..726aad73 100644 --- a/modules/core/json.py +++ b/modules/core/json.py @@ -7,7 +7,9 @@ def json_decode(contents: str|bytes) -> DottedDict: return json.loads(contents, object_hook=object_hook) -def json_encode(obj: Any): +def json_encode(obj: Any, pretty=False): + if pretty: + return json.dumps(obj, cls=JSONEncoder, indent='\t') return json.dumps(obj, cls=JSONEncoder) class DottedDict(dict): #type: ignore diff --git a/modules/core/log.py b/modules/core/log.py index 871675f1..97a0ffd5 100644 --- a/modules/core/log.py +++ b/modules/core/log.py @@ -15,21 +15,6 @@ def log_configure(log_info: bool, log_errors: bool, log_exceptions: bool): _should_log_error = log_errors _should_log_info = log_info - -def log_error(*args: Any) -> None: - if not _should_log_error: - return - print('Debugger: error:', *args) - - -def log_exception(*args: Any) -> None: - import traceback - if not _should_log_exceptions: - return - print(*args, end='') - print(traceback.format_exc()) - - def info(*args: Any) -> None: if not _should_log_info: return @@ -45,8 +30,9 @@ def exception(*args: Any) -> None: import traceback if not _should_log_exceptions: return - print(*args, end='') + print('Debugger:', *args, end='') print(traceback.format_exc()) + print('--') def debug(*args: Any) -> None: diff --git a/modules/core/sublime_event_loop.py b/modules/core/sublime_event_loop.py index 41ed4b38..8416e49b 100644 --- a/modules/core/sublime_event_loop.py +++ b/modules/core/sublime_event_loop.py @@ -98,7 +98,7 @@ def default_exception_handler(self, context): raise NotImplementedError def call_exception_handler(self, context): - from .log import log_exception + from .log import exception from .error import Error try: @@ -108,7 +108,7 @@ def call_exception_handler(self, context): raise Error(context['message']) except Exception as e: - log_exception() + exception() # Debug flag management. def get_debug(self): diff --git a/modules/dap/debugger.py b/modules/dap/debugger.py index 5feaeb84..7a4c9518 100644 --- a/modules/dap/debugger.py +++ b/modules/dap/debugger.py @@ -2,12 +2,12 @@ from ..typecheck import * from ..import core -from . import Session -from . import OutputEvent if TYPE_CHECKING: from .configuration import AdapterConfiguration, ConfigurationExpanded from ..breakpoints import Breakpoints + from . import Session + from . import OutputEvent class Debugger(Protocol): on_error: core.Event[str] diff --git a/modules/dap/session.py b/modules/dap/session.py index 93626e55..176a7461 100644 --- a/modules/dap/session.py +++ b/modules/dap/session.py @@ -1,21 +1,20 @@ from __future__ import annotations - from ..typecheck import * from enum import IntEnum from ..import core +from .import dap + +from ..watch import Watch +from .debugger import Debugger +from .error import Error from ..breakpoints import ( Breakpoints, SourceBreakpoint, ) -from ..watch import Watch - -from .import dap -from .error import Error - from .variable import ( Variable, SourceLocation, @@ -60,7 +59,6 @@ class State (IntEnum): stopped_reason_terminated_event=4 stopped_reason_manual=5 - def __init__(self, adapter_configuration: AdapterConfiguration, configuration: ConfigurationExpanded, @@ -69,7 +67,8 @@ def __init__(self, breakpoints: Breakpoints, watch: Watch, listener: SessionListener, - transport_log: core.Logger, + transport_log: core.Logger, + debugger: Debugger, parent: Session|None = None ) -> None: @@ -81,7 +80,8 @@ def __init__(self, self.listener = listener self.children: list[Session] = [] self.parent = parent - + self.debugger = debugger + if parent: parent.children.append(self) @@ -154,7 +154,7 @@ async def launch(self) -> None: await self.launching_async except core.Error as e: self.launching_async = None - core.log_exception(e) + core.exception(e) self.error('... an error occured, ' + str(e)) await self.stop_forced(reason=Session.stopped_reason_launch_error) except core.CancelledError: @@ -266,7 +266,7 @@ async def run_task(self, name: str, task: TaskExpanded) -> bool: return False except Exception as e: - core.log_exception() + core.exception() self.error(f'{name}: {e}') return False @@ -432,7 +432,7 @@ async def stop(self): }) return except Error as e: - core.log_exception() + core.exception() # we couldn't terminate either not a launch request or the terminate request failed @@ -885,7 +885,7 @@ def on_event(self, event: str, body: Any): elif event == 'loadedSource': self.on_loaded_source_event(body) else: - core.log_error(f'event ignored not implemented {event}') + core.error(f'event ignored not implemented {event}') class Thread: diff --git a/modules/dap/transport.py b/modules/dap/transport.py index e08cfbc6..2f721e35 100644 --- a/modules/dap/transport.py +++ b/modules/dap/transport.py @@ -72,7 +72,7 @@ def read(self): # handle Content-Length: 119\r\n line = self.transport.readline() if not header.startswith(header): - print('Expecting Content-Length: header but did not...') + core.error('Expecting Content-Length: header but did not...') continue size = int(line[header_length:].strip()) @@ -80,8 +80,8 @@ def read(self): #handle \r\n line = self.transport.readline() if line != b'\r\n': - print('Expected \\n\\r but did not find...') - print(line) + core.error('Expected \\n\\r but did not find...') + core.error(line) continue diff --git a/modules/dap/transports.py b/modules/dap/transports.py index 030b162a..5ad5acaf 100644 --- a/modules/dap/transports.py +++ b/modules/dap/transports.py @@ -92,7 +92,7 @@ def dispose(self): try: self.process.kill() except Exception: - core.log_exception() + core.exception() class StdioTransport(Transport): @@ -118,7 +118,7 @@ def _read(self, file: Any, callback: Callable[[str], None]) -> None: core.call_soon_threadsafe(callback, line) except Exception as e: - core.log_exception() + core.exception() break self.process.dispose() @@ -166,7 +166,7 @@ def dispose(self) -> None: try: self.socket.close() except: - core.log_exception() + core.exception() # class StdioSocketTransport(Transport): @@ -194,7 +194,7 @@ def dispose(self) -> None: # core.info(line) # core.call_soon_threadsafe(callback, line) # except Exception as e: -# core.log_exception() +# core.exception() # break # def dispose(self) -> None: diff --git a/modules/debugger.py b/modules/debugger.py index 22d6c88f..f9d952e6 100644 --- a/modules/debugger.py +++ b/modules/debugger.py @@ -67,7 +67,7 @@ def get(window: sublime.Window, create: bool = False) -> Debugger|None: Debugger.instances[id] = instance except core.Error as _: - core.log_exception() + core.exception() Debugger.creating[id] = False @@ -141,6 +141,7 @@ async def launch(self, breakpoints: Breakpoints, adapter: dap.AdapterConfigurati watch=self.watch, listener=self, transport_log=self, + debugger=self, parent=parent) @core.schedule diff --git a/modules/debugger_console.py b/modules/debugger_console.py index ee2928e3..d043d108 100644 --- a/modules/debugger_console.py +++ b/modules/debugger_console.py @@ -7,25 +7,25 @@ from .views import css from .views.variable import VariableComponent -from .output_view import OutputView +from .console_output_view import ConsoleOutputView import sublime class DebuggerConsole: def __init__(self, window: sublime.Window, on_navigate: Callable[[dap.SourceLocation], None]): self.on_navigate = on_navigate self.window = window - self.panel: OutputView|None = None + self.panel: ConsoleOutputView|None = None self.indent = '' def dispose(self): if self.panel: self.panel.dispose() - def acquire_panel(self) -> OutputView: + def acquire_panel(self) -> ConsoleOutputView: if not self.panel or self.panel.is_closed: if self.panel: self.panel.dispose() - self.panel = OutputView(self.window, 'Debugger Console') + self.panel = ConsoleOutputView(self.window, 'Debugger Console') return self.panel diff --git a/modules/debugger_interface.py b/modules/debugger_interface.py index 7d6f24d4..985bcdce 100644 --- a/modules/debugger_interface.py +++ b/modules/debugger_interface.py @@ -181,26 +181,26 @@ async def launch(self, no_debug: bool = False): if not active_configurations: return - except Exception as e: - core.log_exception() - core.display(e) - return + # grab variables before we open the console because the console will become the focus + # and then things like $file would point to the console + variables = self.project.extract_variables() + self.dispose_terminals(unused_only=True) + self.tasks.remove_finished() - # grab variables before we open the console because the console will become the focus - # and then things like $file would point to the console - variables = self.project.extract_variables() + # clear console if there are not any currently active sessions + if not self.debugger.sessions: + self.console.clear() - self.dispose_terminals(unused_only=True) - self.tasks.remove_finished() + self.console.show() + + await self.ensure_installed(active_configurations) - # clear console if there are not any currently active sessions - if not self.debugger.sessions: - self.console.clear() - self.console.show() - - await self.ensure_installed(active_configurations) + except Exception as e: + core.exception() + core.display(e) + return for configuration in active_configurations: @core.schedule diff --git a/modules/panel.py b/modules/panel.py index 69cabc32..aba66d53 100644 --- a/modules/panel.py +++ b/modules/panel.py @@ -206,11 +206,11 @@ def adjust_rem_width_scale(self): adjustment = 0.001 * int(abs(overlap) / 2 + 1) value = Settings.ui_rem_width_scale if overlap > 0: - print(f'overscan {overlap}: adjusting rem_width: {Settings.ui_rem_width_scale}') + core.info(f'overscan {overlap}: adjusting rem_width: {Settings.ui_rem_width_scale}') value = Settings.ui_rem_width_scale - adjustment else: value = Settings.ui_rem_width_scale + adjustment - print(f'underscan {overlap}: adjusting rem_width: {Settings.ui_rem_width_scale}') + core.info(f'underscan {overlap}: adjusting rem_width: {Settings.ui_rem_width_scale}') Settings.ui_rem_width_scale = min(max(value, 0.5), 1.5) diff --git a/modules/persistance.py b/modules/persistance.py index 8ae6b31f..13d6efcb 100644 --- a/modules/persistance.py +++ b/modules/persistance.py @@ -4,7 +4,6 @@ from .import core import os -import sublime import hashlib @@ -22,7 +21,7 @@ def load(project_name: str) -> Any: contents = file.read() or "{}" json = core.json_decode(contents) - if json.get("version") == VERSION_NUMBER: + if json.get("_version") == VERSION_NUMBER: return json except FileNotFoundError: @@ -32,8 +31,9 @@ def load(project_name: str) -> Any: def save(project_name: str, data: Any): file_name = file_name_for_project_name(project_name) with open(file_name, 'w') as file: - data['version'] = VERSION_NUMBER - file.write(core.json_encode(data)) + data['_version'] = VERSION_NUMBER + data['_project_name'] = project_name + file.write(core.json_encode(data, pretty=True)) diff --git a/modules/schema.py b/modules/schema.py index 57d2a486..a2d0eb6c 100644 --- a/modules/schema.py +++ b/modules/schema.py @@ -87,7 +87,6 @@ def save_schema(adapters: list[dap.AdapterConfiguration]): # 'bodyText': core.json_encode_json_language_service_format(snippet['body']), 'description': snippet.get('description') }) - print(snippet) debugger_configurations = { 'type': 'object', diff --git a/modules/settings.py b/modules/settings.py index 94f776e1..04fd512d 100644 --- a/modules/settings.py +++ b/modules/settings.py @@ -3,7 +3,6 @@ from typing import Any, Callable import sublime -from .import core class SettingsMeta(type): def __getattribute__(self, key: str) -> Any: diff --git a/modules/source_navigation.py b/modules/source_navigation.py index 05aded63..e8e5aa4d 100644 --- a/modules/source_navigation.py +++ b/modules/source_navigation.py @@ -55,7 +55,7 @@ def select_source_location(self, source: dap.SourceLocation, stopped_reason: str def on_error(error: BaseException): if error is not core.CancelledError: - core.log_error(error) + core.error(error) async def select_async(source: dap.SourceLocation, stopped_reason: str): self.clear_selected() @@ -73,7 +73,7 @@ def show_source_location(self, source: dap.SourceLocation): def on_error(error: BaseException): if error is not core.CancelledError: - core.log_error(error) + core.error(error) async def navigate_async(source: dap.SourceLocation): self.clear_generated_view() diff --git a/modules/terminal_integrated.py b/modules/terminal_integrated.py index 583178d9..8f8b551d 100644 --- a/modules/terminal_integrated.py +++ b/modules/terminal_integrated.py @@ -1,7 +1,7 @@ from __future__ import annotations from .typecheck import * -from .output_view import OutputView +from .console_output_view import ConsoleOutputView from .typecheck import * from .import core @@ -15,7 +15,7 @@ class TerminalIntegrated: def __init__(self, window: sublime.Window, name: str, command: list[str], cwd: str|None): cwd = cwd or None # turn "" into None or PtyProcess will lockup? self.process = TtyProcess(command, on_output=self.on_process_output, cwd=cwd, on_close=self.on_process_closed) - self.panel = OutputView(window, 'Terminal', self.on_output_closed) + self.panel = ConsoleOutputView(window, 'Terminal', self.on_output_closed) self.panel.write('') self.closed = False @@ -87,7 +87,7 @@ def _read(self, callback: Callable[[str], None]) -> None: except EOFError as err: break except Exception as err: - core.log_exception() + core.exception() break self.close() @@ -107,4 +107,4 @@ def dispose(self) -> None: try: self.close() except Exception as e: - core.log_exception(e) + core.exception(e) diff --git a/modules/terminal_task.py b/modules/terminal_task.py index b51acb97..baad13f5 100644 --- a/modules/terminal_task.py +++ b/modules/terminal_task.py @@ -11,7 +11,7 @@ from .import dap from .panel import OutputPanel -from .output_view import OutputView +from .console_output_view import ConsoleOutputView @dataclass class Problem: @@ -36,6 +36,7 @@ class Diagnostics(TypedDict): errors: list[Diagnostic] class TerminalTask: + def __init__(self, window: sublime.Window, task: dap.TaskExpanded, on_closed: Callable[[], None]): arguments = task.copy() name: str @@ -52,7 +53,7 @@ def __init__(self, window: sublime.Window, task: dap.TaskExpanded, on_closed: Ca self.background = arguments.get('background', False) self.name = name - self.view = OutputView(window, 'Task', on_closed) + self.view = ConsoleOutputView(window, 'Task', on_closed) self.finished = False # if we don't remove these additional arguments Default.exec.ExecCommand will be unhappy @@ -93,7 +94,7 @@ def dispose(self): try: self.command.proc.kill() except Exception as e: - core.log_exception(e) + core.exception(e) self.command.hide_annotations() self.on_view_load_listener.dispose() diff --git a/modules/views/variable.py b/modules/views/variable.py index 337d4647..2b53357d 100644 --- a/modules/views/variable.py +++ b/modules/views/variable.py @@ -69,7 +69,7 @@ async def on_edit_variable_async(value: str): self.variable.fetched = None self.dirty() except core.Error as e: - core.log_exception() + core.exception() core.display(e) def on_edit_variable(value: str): @@ -88,7 +88,7 @@ async def copy_value(): return except dap.Error as e: - core.log_exception() + core.exception() sublime.set_clipboard(value) diff --git a/start.py b/start.py index a040c113..4d25e115 100644 --- a/start.py +++ b/start.py @@ -18,7 +18,8 @@ from .modules.core.sublime import DebuggerAsyncTextCommand, DebuggerEventsListener from .modules.autocomplete import AutocompleteEventListener -from .modules.output_view import DebuggerPreConsoleWindowHooks, DebuggerPostConsoleViewHooks, DebuggerPostConsoleWindowHooks +from .modules.console_output_view import DebuggerPreConsoleWindowHooks, DebuggerPostConsoleViewHooks, DebuggerPostConsoleWindowHooks + from .modules.typecheck import * from .modules import core @@ -46,7 +47,7 @@ def plugin_loaded() -> None: ui.startup() for window in sublime.windows(): - open(window) + open_debugger_in_window_or_view(window) def plugin_unloaded() -> None: @@ -57,7 +58,7 @@ def plugin_unloaded() -> None: ui.shutdown() -def open(window_or_view: Union[sublime.View, sublime.Window]): +def open_debugger_in_window_or_view(window_or_view: Union[sublime.View, sublime.Window]): if isinstance(window_or_view, sublime.View): window = window_or_view.window() else: @@ -108,7 +109,7 @@ def ignore(self, view: sublime.View): return not bool(Debugger.instances) def on_new_window(self, window: sublime.Window): - open(window) + open_debugger_in_window_or_view(window) def on_pre_close_window(self, window: sublime.Window): if debugger := Debugger.get(window): @@ -172,7 +173,7 @@ def on_close(): # errors trying to evaluate a hover expression should be ignored except dap.Error as e: - core.log_error('adapter failed hover evaluation', e) + core.error('adapter failed hover evaluation', e) def on_text_command(self, view: sublime.View, cmd: str, args: dict[str, Any]) -> Any: if self.ignore(view): return @@ -205,8 +206,6 @@ def on_view_gutter_clicked(self, view: sublime.View, line: int, button: int) -> if not debuggers: return False - items: list[ui.InputListItem] = [] - for debugger in debuggers: breakpoints = debugger.breakpoints file = view.file_name()