From 0365c54a9e2638890360d60dfba501c2944fb2cc Mon Sep 17 00:00:00 2001 From: Colin Watson Date: Fri, 3 May 2024 16:31:23 +0100 Subject: [PATCH] Playing with rich --- content/playing-with-rich.md | 74 ++++++++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) create mode 100644 content/playing-with-rich.md diff --git a/content/playing-with-rich.md b/content/playing-with-rich.md new file mode 100644 index 00000000..29c4020c --- /dev/null +++ b/content/playing-with-rich.md @@ -0,0 +1,74 @@ +Title: Playing with rich +Slug: playing-with-rich +Date: 2024-05-03 16:09:53 +01:00 +Category: columbiform +Tags: columbiform, freexian, planet-debian, planet-ubuntu + +One of the things I do as a side project for Freexian is to work on various +bits of business automation: accounting tools, programs to help contributors +report their hours, invoicing, that kind of thing. While it's not quite my +usual beat, this makes quite a good side project as the tools involved are +mostly rather sensible and easy to deal with (Python, git, +[ledger](https://ledger-cli.org/), that sort of thing) and it's the kind of +thing where I can dip into it for a day or so a week and feel like I'm +making useful contributions. The logic can be quite complex, but there's +very little friction in the tools themselves. + +A recent case where I did run into some friction in the tools was with some +commands that need to present small amounts of tabular data on the terminal, +using [OSC +8](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda) +hyperlinks if the terminal supports them: think customer-related information +with some links to issues. One of my colleagues had previously done this +using a [hack](https://github.com/foutaise/texttable/issues/87) on top of +[texttable](https://pypi.org/project/texttable/), which was perfectly fine +as far as it went. However, now I wanted to be able to add multiple links +in a single table cell in some cases, and that was really going to stretch +the limits of that approach: working out the width of the displayed text in +the cell was going to take an annoying amount of bookkeeping. + +I started looking around to see whether any other approaches might be +easier, without too much effort (remember that "a day or so a week" bit +above). [ansiwrap](https://pypi.org/project/ansiwrap/) looked somewhat +promising, but it isn't currently packaged in Debian, and it would have +still left me with the problem of figuring out how to integrate it into +`texttable`, which looked like it would be quite complicated. Then I +remembered that I'd heard good things about +[rich](https://pypi.org/project/rich/), and thought I'd take a look. + +`rich` turned out to be exactly what I wanted. Instead of something like +this based on the `texttable` hack above: + + :::python + import shutil + from pyxian.texttable import UrlTable + + termsize = shutil.get_terminal_size((80, 25)) + table = UrlTable(max_width=termsize.columns) + table.set_deco(UrlTable.HEADER) + table.set_cols_align(["l"]) + table.set_cols_dtype(["u"]) + table.add_row(["Issue"]) + table.add_row([(issue_url, f"#{issue_id}")] + print(table.draw()) + +... now I can do this instead: + + :::python + import rich + from rich import box + from rich.table import Table + + table = Table(box=box.SIMPLE) + table.add_column("Issue") + table.add_row(f"[link={issue_url}]#{issue_id}[/link]") + rich.print(table) + +While this is a little shorter, the real bonus is that I can now just put +multiple `[link]` tags in a single string, and it all just works. No +ceremony. In fact, once the relevant bits of code passed type-checking +(since the real code is a bit more complex than the samples above), it +worked first time. It's a pleasure to work with a library like that. + +It looks like I've only barely scratched the surface of `rich`, but I expect +I'll reach for it more often now. -- 2.30.2