Skip to content

air: Fit air list to narrow terminals by compacting and then hiding columns - #7629

Open
dimk0 wants to merge 4 commits into
mainfrom
air-list-narrow-columns
Open

dimk0 wants to merge 4 commits into
mainfrom
air-list-narrow-columns

Conversation

@dimk0

@dimk0 dimk0 commented Nov 14, 2026 •

Copy link
Copy Markdown
Member

Changes

Follow-up to #7583 for CNXT-2619. The interactive databricks air list table shrank Experiment and User to their floors, but every other column kept a fixed or content width, so below about 134 columns the rightmost columns were still cut off (Progress at 80 columns, Accelerators and most of User at 120).

When the table is still too wide once Experiment and User reach their floors, two more tiers now apply, in order:

  1. Compact. Started switches to MM-DD HH:MM (11 cells instead of 19) and the MLflow column is sized to its widest stored label instead of a fixed 22 cells. The stored labels are not re-truncated, so they keep their end and their retry note (air: Shorten MLflow run names and IDs the same way in air list #7582).
  2. Hide. Whole columns are dropped lowest priority first (Accelerators, then User, then MLflow, then Progress) until the table fits or nothing is left to hide. The hint line names the hidden columns, e.g. hidden: MLflow, User, Accelerators. The hint must itself fit the terminal, or bubbletea cuts off its end (where the loading / load-failed state sits), so it gives up detail in steps: the legend shortens to ↑/↓ ←/→ ↵ i L q, then the hidden columns are counted (3 columns hidden), then the legend goes, and as a last resort the line is truncated. The row counter and paging state come first, so they survive every step. The variant is chosen for the widest row counter and the loading state, so it does not flip as the cursor moves or a page loads.

After each step the spare cells go back to Experiment and User, so they widen again rather than staying at the floors. Enter still opens the row's MLflow link when the MLflow column is hidden. Lazily loaded pages are laid out against the same width; since a new page can only widen the natural columns, the layout moves one way as pages load (a column may compact or disappear mid-scroll, never reappear).

Unchanged:

  • The one-shot table (piped, NO_COLOR, --limit) is byte-for-byte the same.
  • A terminal wide enough for today's table renders exactly as it does today.

Implementation: listCols gains a listColumn enum, an mlflow width, a compactStarted flag and a hidden bitmask; layoutListCols(rows, width) runs the tiers; the header and row renderers iterate the enum and skip hidden columns.

Before / after at 80 columns (e2-dogfood)

Before:

   Run ID            Experiment    Status      Started              Duration  Pr
▸  215643000685172   …b8dfeedf62e  ● SUCCESS   2026-11-14T01:48:45    3m 13s

After:

   Run ID            Experiment      Status      Started      Duration  Progress
▸  392039360633569   …g-v14-1114-v2  ● FAILED    11-14 02:26    6m 53s         -
   215643000685172   …51b8dfeedf62e  ● SUCCESS   11-14 01:48    3m 13s         -
↑/↓ ←/→ ↵ i L q  ·  row 1/20  ·  hidden: MLflow, User, Accelerators

At 120 columns only Accelerators is hidden; at 133 the compact tier alone fits with every column shown; at 134 and above the layout is unchanged.

Why

CNXT-2619 asked for a product decision between compacting fixed columns and hiding low-priority ones. Both are needed: with real data every MLflow label is already 22 cells, so compacting alone only covers terminals from 126 to 133 columns. Hiding is what gets 80 and 100 columns to a readable table.

Tests

  • New unit tests: TestLayoutListCols (0, 60, 80, 100, 120, 133, 160, 200 columns with short MLflow labels), TestLayoutListColsFullLabels (100, 120, 125, 126, 133 columns with 22-cell labels, the widest list.go produces and the usual case for MLflow-named runs), TestLayoutListColsMovesOneWayAsPagesLoad, TestLayoutListColsMLflowFloorIsHeader, TestLayoutListColsCapsMLflowAtColumnWidth, TestStartedCompact, TestHiddenNote, TestRenderHidesColumns, TestListModelNarrowTerminalHidesColumns, TestListModelHintNamesHiddenColumnsWithFullLegend, TestListModelHintFitsNarrowTerminal (40, 46, 70, 75, 80, 100 columns, 120 rows, idle / loading / load failed), TestListModelRelayoutsLoadedPageInNarrowTerminal, TestListModelEnterOpensMLflowLogsWhenColumnHidden. The existing TestStaticListTableIgnoresTerminalWidth and TestListColsFitWidth still pass unchanged.
  • Ran the built CLI in a real pty at 70, 75, 80, 100, 120, 133, 134 and 160 columns against the e2-dogfood profile with air list --all-status --all-users: no table or hint line exceeds the terminal width at any size, and 134 and 160 match the main build.
  • Diffed piped output and --limit output in a pty between the main build and this branch: identical.
  • golangci-lint run ./cmd/air/... clean.

This pull request and its description were written by Isaac.

dimk0 and others added 2 commits November 14, 2026 02:40
… columns

After #7583 the interactive table shrinks Experiment and User to their
floors, but the other columns keep fixed widths, so below about 134
columns the rightmost columns are still cut off.

When the table is still too wide at the floors, two more tiers apply:

1. Compact: Started becomes `MM-DD HH:MM` and the MLflow column is sized
   to its widest stored label instead of a fixed 22 cells. Labels are not
   re-truncated, so they keep their end and retry note (#7582).
2. Hide: whole columns are dropped lowest priority first (Accelerators,
   User, MLflow, Progress) until the table fits. The hint line names the
   hidden columns; when the full key legend and that note do not both fit,
   the legend shortens to its keys.

After each step the spare cells go back to Experiment and User. Enter
still opens the row's MLflow link when the MLflow column is hidden.

The one-shot table (piped, NO_COLOR, --limit) and terminals wide enough
for today's table render exactly as before.

Verified with unit tests at 80, 100, 120, 133, 160 and 200 columns and by
running the CLI in a pty at those widths against e2-dogfood.

CNXT-2619

Co-authored-by: Isaac <[email protected]>
@github-actions github-actions Bot added the AIR Databricks AI Runtime CLI label Nov 14, 2026
@eng-dev-ecosystem-bot

eng-dev-ecosystem-bot commented Nov 14, 2026 •

Copy link
Copy Markdown
Collaborator

✅ Integration test report

Commit: 74de95f

Run: 43552943503

Env 💚​RECOVERED ✅​pass 🙈​skip Time
💚​ aws linux-2core-8gb 1 270 15 3:58
💚​ aws-windows-latest-4core-16gb 1 272 13 2:59
💚​ azure linux-2core-8gb 1 269 15 3:20
💚​ azure-windows-latest-4core-16gb 1 271 13 2:50
💚​ gcp linux-2core-8gb 1 270 15 3:30
💚​ gcp-windows-latest-4core-16gb 1 272 13 2:46
Test Name aws linux-2core-8gb aws-windows-latest-4core-16gb azure linux-2core-8gb azure-windows-latest-4core-16gb gcp linux-2core-8gb gcp-windows-latest-4core-16gb
💚​ TestAccept 💚​R 💚​R 💚​R 💚​R 💚​R 💚​R
Top 3 slowest tests (at least 2 minutes):
duration env testname
2:54 aws-windows-latest-4core-16gb TestAccept
2:45 azure-windows-latest-4core-16gb TestAccept
2:39 gcp-windows-latest-4core-16gb TestAccept

dimk0 and others added 2 commits November 14, 2026 03:32
…Lflow label width

Review follow-ups for #7629.

The hint line could still run past the terminal, and bubbletea cut off
its end, which is where the loading / load-failed state sat. The hint
now gives up detail in steps until it fits: the legend shrinks to its
keys, then the hidden columns are counted instead of named, and as a
last resort the line is truncated. The variant is chosen for the widest
row counter and the loading state, so it does not flip as the cursor
moves or a page loads.

Tests now also cover the production case where every MLflow label is
the full 22 cells, the Progress tier, the still-too-wide case, a page
load that crosses a tier, the selected row in a reduced layout, and the
hint at 70, 75, 80 and 100 columns in every paging state.

Also: cap the compact MLflow width at mlflowColWidth, show a non-ISO
start timestamp as is instead of slicing it, decide right alignment in
one place, drop the duplicated link check in mlflowCell, and trim doc
comments.

Co-authored-by: Isaac <[email protected]>
…as no room for a legend

Below the width where even the short legend fits, the hint now drops the
legend before truncating, so the row counter and loading / load-failed
state stay visible. Also test the MLflow width cap, compare whole hints
in the stability check, and say that mlflowColWidth is the widest label
list.go produces rather than the only one.

Co-authored-by: Isaac <[email protected]>
@dimk0
dimk0 marked this pull request as ready for review November 14, 2026 04:03
@dimk0
dimk0 requested review from a team as code owners November 14, 2026 04:03
@dimk0
dimk0 requested a review from rugpanov November 14, 2026 04:03

@maggiewang-db maggiewang-db left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Don't mention internal jira tickets in open source repo.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AIR Databricks AI Runtime CLI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants