From e85f16d4d71ae0482e0f4404fce1b6ee516a4d72 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Wed, 7 Jan 2026 22:49:02 +0000 Subject: [PATCH] feat(cli): Add clickable hyperlinks to Profile IDs in summary table - Implemented `Colors.link` helper for OSC 8 hyperlinks. - Updated summary table to linkify Profile IDs. - Fixed table alignment issue caused by ANSI escape codes by manually calculating padding. - Added UX learning to `.jules/palette.md`. --- .jules/palette.md | 4 ++++ main.py | 14 +++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/.jules/palette.md b/.jules/palette.md index fbedb303..b6f0448c 100644 --- a/.jules/palette.md +++ b/.jules/palette.md @@ -14,3 +14,7 @@ ## 2024-03-22 - CLI Interactive Fallbacks **Learning:** CLI tools often fail hard when config is missing, but interactive contexts allow for graceful recovery. Users appreciate being asked for missing info instead of just receiving an error. **Action:** When `sys.stdin.isatty()` is true, prompt for missing configuration instead of exiting with an error code. + +## 2025-05-24 - CLI Hyperlinks & Alignment +**Learning:** Adding ANSI escape codes (like hyperlinks) to CLI tables breaks standard column alignment because the string length increases invisibly. +**Action:** When adding hyperlinks to table cells, manually calculate padding based on the visible text length, not the full string length. diff --git a/main.py b/main.py index e6aabc57..9433eaa7 100644 --- a/main.py +++ b/main.py @@ -59,6 +59,12 @@ class Colors: BOLD = '' UNDERLINE = '' + @staticmethod + def link(text: str, url: str) -> str: + if not USE_COLORS: + return text + return f"\033]8;;{url}\033\\{text}\033]8;;\033\\" + class ColoredFormatter(logging.Formatter): """Custom formatter to add colors to log levels.""" LEVEL_COLORS = { @@ -844,8 +850,14 @@ def main(): # Use boolean success field for color logic status_color = Colors.GREEN if res['success'] else Colors.FAIL + # Create clickable profile ID + pid = res['profile'] + # Pad manually because ANSI codes confuse f-string alignment + padding = " " * (profile_col_width - len(pid)) + linked_pid = Colors.link(pid, f"https://controld.com/profiles/{pid}") + print( - f"{res['profile']:<{profile_col_width}} | " + f"{linked_pid}{padding} | " f"{res['folders']:>10} | " f"{res['rules']:>10,} | " f"{res['duration']:>9.1f}s | "