From c44c41b1886323658f1600218084457dbc1ae8d5 Mon Sep 17 00:00:00 2001 From: Dan Ilan <15796788+jmpfar@users.noreply.github.com> Date: Sun, 29 Dec 2024 00:57:26 +0200 Subject: [PATCH] feat: add terminal hyperlinks to diagnostic check name See https://iterm2.com/feature-reporting/Hyperlinks_in_Terminal_Emulators.html for information about terminal hyperlinks. This is supported by multiple terminals and makes it easier to find out more information about a failing check. --- clangd_tidy/diagnostic_formatter.py | 29 +++++++++++++++++++++++++++-- clangd_tidy/lsp/messages.py | 7 ++++++- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/clangd_tidy/diagnostic_formatter.py b/clangd_tidy/diagnostic_formatter.py index 22fa24c..da6e646 100644 --- a/clangd_tidy/diagnostic_formatter.py +++ b/clangd_tidy/diagnostic_formatter.py @@ -1,7 +1,7 @@ -from abc import ABC, abstractmethod import os import pathlib import re +from abc import ABC, abstractmethod from typing import Dict, Iterable, List, Optional from .lsp.messages import Diagnostic, DiagnosticSeverity @@ -150,6 +150,10 @@ class ColorSeqTty: MAGENTA = "\033[95m" BOLD = "\033[1m" ENDC = "\033[0m" + START_LINK = "\033]8;;" + END_LINK = "\033\\" + + colors_enabled = True class ColorSeqNoTty: ERROR = "" @@ -161,6 +165,10 @@ class ColorSeqNoTty: MAGENTA = "" BOLD = "" ENDC = "" + START_LINK = "" + END_LINK = "" + + colors_enabled = False def __init__(self, enable_color: bool): self.color_seq = self.ColorSeqTty if enable_color else self.ColorSeqNoTty @@ -185,6 +193,18 @@ def note(self, message: str): def format(self, message: str): return f"{self.color_seq.MAGENTA}{message}{self.color_seq.ENDC}" + def link(self, message: str, url: str | None): + if url is None: + return message + + if not self.color_seq.colors_enabled: + return message + + return ( + f"{self.color_seq.START_LINK}{url}{self.color_seq.END_LINK}" + f"{message}{self.color_seq.START_LINK}{self.color_seq.END_LINK}" + ) + def __init__(self, extra_context: int, enable_color: bool): self._extra_context = extra_context self._colorizer = self.Colorizer(enable_color) @@ -269,7 +289,12 @@ def _format_one_diagnostic( if diagnostic.code is None: return None - code = f"[{diagnostic.code}]" + + code_url = None + if diagnostic.codeDescription: + code_url = diagnostic.codeDescription.href + format_code = self._colorizer.link(diagnostic.code, code_url) + code = f"[{format_code}]" severity = ( self._colorized_severity(diagnostic.severity.value) diff --git a/clangd_tidy/lsp/messages.py b/clangd_tidy/lsp/messages.py index 2da591a..9be9a75 100644 --- a/clangd_tidy/lsp/messages.py +++ b/clangd_tidy/lsp/messages.py @@ -116,13 +116,18 @@ def __lt__(self, other) -> bool: return NotImplemented +@define +class CodeDescription: + href: str + + @define class Diagnostic: range: Range message: str severity: Optional[DiagnosticSeverity] = None code: Any = None - codeDescription: Any = None + codeDescription: CodeDescription = None source: Optional[str] = None tags: Optional[List[Any]] = None relatedInformation: Optional[List[Any]] = None