Enable tables to carry a title or footer
A detailed description of the feature you would like to see added.
I was looking to implement https://github.com/bytecodealliance/wasm-tools/issues/1923 using comfy-table to get a duf-like output, but it doesn't seem comfy-table is able to set titles. It would be neat if it could though.
Explain your usecase of the requested feature
When printing many tables in a row, being able to render a title adds some visual rhythm, making it easier to scan for the section you're looking for.
Alternatives
No response
Additional context
This is the output I'm trying to create:

┌──────────────────────────────────────┐
│ component sample-wasi-http-rust │
├──────────┬────────────────┬──────────┤
│ KIND │ PRODUCER │ VERSION │
├──────────┼────────────────┼──────────┤
│ tool │ wit-component │ 0.216.0 │
└──────────┴────────────────┴──────────┘
┌──────────────────────────────────────────────────────────────────────────────────┐
│ module sample_wasi_http_rust.wasm │
├──────────┬──────────────────┬────────────────────────────────────────────────────┤
│ KIND │ PRODUCER │ VERSION │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ language │ Rust │ - │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ language │ C11 │ - │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ tool │ rustc │ 1.82.0 (f6e511eec 2024-10-15) │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ tool │ clang │ 18.1.2-wasi-sdk │
│ │ │ (https://github.com/llvm/llvm-project │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ tool │ wit-component │ 0.20.1 │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ tool │ wit-bindgen-rust │ 0.20.1 │
├──────────┼──────────────────┼────────────────────────────────────────────────────┤
│ tool │ wit-bindgen-c │ 0.20.1 │
└──────────┴──────────────────┴────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────┐
│ module wit-component:adapter:wasi_snapshot_preview1: │
├──────────┬──────────┬────────────────────────────────┤
│ KIND │ PRODUCER │ VERSION │
├──────────┼──────────┼────────────────────────────────┤
│ language │ Rust │ - │
├──────────┼──────────┼────────────────────────────────┤
│ tool │ rustc │ 1.82.0 (f6e511eec 2024-10-15) │
└──────────┴──────────┴────────────────────────────────┘
┌────────────────────────────────────┐
│ module wit-component-shim │
├──────────┬───────────────┬─────────┤
│ KIND │ PRODUCER │ VERSION │
├──────────┼───────────────┼─────────┤
│ language │ Rust │ - │
├──────────┼───────────────┼─────────┤
│ tool │ wit-component │ 0.216.0 │
└──────────┴───────────────┴─────────┘
┌────────────────────────────────────┐
│ module wit-component:fixups │
├──────────┬───────────────┬─────────┤
│ KIND │ PRODUCER │ VERSION │
├──────────┼───────────────┼─────────┤
│ language │ Rust │ - │
├──────────┼───────────────┼─────────┤
│ tool │ wit-component │ 0.216.0 │
└──────────┴───────────────┴─────────┘
I like that!
Should also be fairly easy to implement as the last step before the rendered table is returned :)
A few things must be done for this to be implemented properly:
- It must support alignment
- Padding?
- Same border display logic as the rest of the table
- Styling?
Most of this logic can probably be re-used from the formatting module, the current code will need a bit of refactoring though. It's very much entangled with ColumnDisplayInfo and Cell.
Should we re-use the Cell for this and let table.set_title(title: Cell) accept a cell?
Yay, I'm glad you like it!
Should we re-use the Cell for this and let
table.set_title(title: Cell)accept a cell?
That seems reasonable to me. It essentially is one big cell, so that doesn't seem like a bad starting point.
Padding?
This would be nice to have, yes. At least for my use case I don't think we will immediately need it, but I could see us using this.
If you got some spare time, feel free to start tackling this one :)
Otherwise I might get to it eventually (I hope :D), should be a fun task.
I probably won't get around to taking a stab at this myself for a while, so please don't let me hold you back from implementing something fun ^^
Turns out, I have enough to do myself :D
If anybody wants to work on this, feel free to do so :) I won't work on this for the forseeable future.
So, I played around with this for a bit and turns out, this is quite a bit more tricky than expected.
The current logic for determining column sizes is column-based. Roughly explained, it works by looking at constraints and contents of the columns and trying to distribute the content in a way that the given space is used as efficiently as possible. It's a classic optimization problem where we try to find a near-perfect solution in an acceptable amount of time.
For tables that always match the full size of the terminal, adding a title is rather trivial. It gets pretty tricky though, when the title is larger than the table's content! In that case, the space distribution algorithm must be adjusted to allow setting a "overall min-width" value (the width of the title), which is then respected when the column sizes are determined. So the column sizes are no longer only depending on the columns, but also on external factors (the title). This might result in columns becoming larger than the algorithm would currently determine.
It's all doable, but the current code is pretty involved, including many loose variables. To prevent this whole thing from being even more confusing, I think we need some kind of abstraction/some kind of struct, that holds all of the layout relevant information and provides convenience helper functions with proper documentation on what the various variables mean and how they're used to determine column sizes and lateron how the table is formatted based on those values.
I already have a few ideas, but this will result in a bit of a larger refactoring, so I'm unsure when I'll get to it.
@Nukesor thank you for looking into this, and thank you for the update!
If anybody feels like tackling this issue, feel free to go ahead (just give a quick note to prevent two people working on the same thing) :D
As I sad above, this will probably need a bit of refactoring to keep the code sane. One way of keeping this clean would be to have a state struct being passed around in arrangement::dynamic::arrange, instead of having loads of individual variables. That would keep things organized and allow us to create a few helper functions for operations that manipulate multiple variables at the same time (that should then be tested).
As requested by @asyd, a footer in the style of the title could also be added at the bottom of the table.
As a kind of stupid workaround:
- Build the first table
- Detect the width by checking the first line
- Build another table with a single cell and that exact width
- Style it so that it doesn't have a top/bottom border
- Concat