Skip to content

feat(format): add NoWrapCell for data-driven column minimum widths#574

Merged
apstndb merged 1 commit intomainfrom
issue-567-nowrap-cell
Mar 20, 2026
Merged

feat(format): add NoWrapCell for data-driven column minimum widths#574
apstndb merged 1 commit intomainfrom
issue-567-nowrap-cell

Conversation

@apstndb
Copy link
Owner

@apstndb apstndb commented Mar 20, 2026

Summary

  • Add NoWrapCell type that wraps any Cell to indicate its content should preferably not be wrapped
  • Add deriveColumnHints() to compute PreferredMinWidth per column from NoWrapCell instances
  • Update ColumnHint with PreferredMinWidth field (replaces reserved NoWrap bool)
  • Add applyColumnFloors() shared helper with soft degradation: uses preferred min when budget allows, falls back to hard minimum when it doesn't fit
  • Wrap NULL cells as NoWrapCell in spannerRowToRow()
  • Reduce minColumnWidth from 4 to 1 (meaningful minimum is now data-driven)

Motivation

The hardcoded minColumnWidth = 4 was implicit knowledge that NULL is 4 characters. This change makes the constraint data-driven and soft: columns with NoWrapCell values prefer to be wide enough to avoid wrapping those values, but degrade gracefully when screen space is insufficient.

Test plan

  • NoWrapCell type: Format/RawText delegation, WithText preserves wrapper, IsNoWrap helper
  • deriveColumnHints: computes correct PreferredMinWidth from NoWrapCell widths
  • All strategies respect PreferredMinWidth when space allows
  • Graceful degradation when preferred mins exceed available width
  • make check passes (test + lint + fmt-check)

Fixes #567

🤖 Generated with Claude Code

Replace the hardcoded minColumnWidth=4 (for NULL marker) with a general
NoWrapCell mechanism that marks cells whose content should preferably
not be wrapped.

- Add NoWrapCell type wrapping any Cell via composition
- Add deriveColumnHints() to compute PreferredMinWidth per column from
  NoWrapCell instances
- Update ColumnHint with PreferredMinWidth field (replaces NoWrap bool)
- Add applyColumnFloors() shared helper with soft degradation: uses
  preferred min when budget allows, falls back to hard minimum (1) when
  preferred mins exceed available width
- Update spannerRowToRow() to wrap NULL cells as NoWrapCell
- Reduce minColumnWidth from 4 to 1 (meaningful minimum is now data-driven)
- All three strategies (Greedy, Marginal, Proportional) use the shared helper

Fixes #567

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the table formatting capabilities by introducing a data-driven approach to column width management. It allows specific cell contents to express a preference against wrapping, ensuring that short, important values remain intact when possible. The system now dynamically calculates preferred minimum widths and applies them with a soft degradation mechanism, providing a more intelligent and visually appealing layout that adapts gracefully to available screen space, moving away from rigid, hardcoded minimums.

Highlights

  • New NoWrapCell Type: Introduced a NoWrapCell type that wraps any Cell to indicate its content should preferably not be wrapped, allowing for data-driven minimum column widths.
  • Dynamic Preferred Minimum Width Calculation: Added deriveColumnHints() to compute PreferredMinWidth for each column by scanning NoWrapCell instances, ensuring short values like 'NULL' are preserved.
  • Updated ColumnHint Structure: Modified the ColumnHint struct to include PreferredMinWidth (an integer) which replaces the previously reserved NoWrap bool field.
  • Flexible Column Floor Application: Implemented applyColumnFloors() as a shared helper that intelligently applies per-column minimum widths, using preferred minimums when space allows and gracefully degrading to a hard minimum when the budget is exceeded.
  • Reduced Hardcoded Minimum Column Width: Decreased the global minColumnWidth constant from 4 to 1, shifting the responsibility for meaningful minimums to the new data-driven NoWrapCell logic.
  • NULL Cells Wrapped as NoWrapCell: Ensured that NULL cells are now wrapped as NoWrapCell instances in spannerRowToRow() and integration tests, allowing them to benefit from the new preferred minimum width logic.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link

Code Metrics Report

📊 View detailed coverage report (available for 7 days)

main (f3a08a1) #574 (cf150bc) +/-
Coverage 70.7% 70.8% +0.1%
Code to Test Ratio 1:1.2 1:1.3 +0.0
Test Execution Time 2m24s 1m9s -1m15s
Details
  |                     | main (f3a08a1) | #574 (cf150bc) |  +/-   |
  |---------------------|----------------|----------------|--------|
+ | Coverage            |          70.7% |          70.8% |  +0.1% |
  |   Files             |             75 |             75 |      0 |
  |   Lines             |           6988 |           7007 |    +19 |
+ |   Covered           |           4945 |           4967 |    +22 |
+ | Code to Test Ratio  |          1:1.2 |          1:1.3 |   +0.0 |
  |   Code              |          16241 |          16274 |    +33 |
+ |   Test              |          21086 |          21183 |    +97 |
+ | Test Execution Time |          2m24s |           1m9s | -1m15s |

Code coverage of files in pull request scope (90.8% → 91.7%)

Files Coverage +/- Status
internal/mycli/execute_sql.go 82.6% +1.3% affected
internal/mycli/format/config.go 100.0% 0.0% modified
internal/mycli/format/width.go 96.9% -0.6% modified
internal/mycli/format/width_strategy.go 100.0% 0.0% modified
internal/mycli/format/width_strategy_greedy.go 97.8% -0.1% modified
internal/mycli/format/width_strategy_marginal.go 96.3% -0.1% modified
internal/mycli/format/width_strategy_proportional.go 100.0% 0.0% modified
internal/mycli/metrics/execution_metrics.go 91.1% +4.4% affected
internal/mycli/row_iter.go 87.0% 0.0% modified

Reported by octocov

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a NoWrapCell type and a PreferredMinWidth concept to enhance column width calculation in table formatting. The minColumnWidth is reduced from 4 to 1, and a new mechanism is implemented to identify cells that should preferably not be wrapped (e.g., "NULL", "true", "false"). The system now calculates a PreferredMinWidth for each column based on the maximum width of its NoWrapCell contents. Column width strategies have been updated to utilize these PreferredMinWidth hints, applying them as a soft constraint when space allows, and gracefully degrading to the hard minColumnWidth of 1 if the total preferred width exceeds available screen space. This ensures important short values remain intact while maintaining flexibility in layout. New unit and integration tests have been added to validate this behavior, particularly for NULL values.

@apstndb
Copy link
Owner Author

apstndb commented Mar 20, 2026

/gemini summary

@gemini-code-assist
Copy link
Contributor

Summary of Changes

This pull request refactors the column width calculation logic to be data-driven, moving away from a hardcoded minimum width. It introduces a NoWrapCell type to allow cell content to express a preference against wrapping, which is then used to compute preferred minimum widths for columns. This enables a more intelligent and visually appealing table layout that prioritizes keeping short, important values intact while gracefully degrading when screen space is limited.

Highlights

  • New NoWrapCell Type: Introduced a NoWrapCell type that wraps any Cell to indicate its content should preferably not be wrapped, allowing for data-driven minimum column widths.
  • Dynamic Preferred Minimum Width Calculation: Added deriveColumnHints() to compute PreferredMinWidth for each column by scanning NoWrapCell instances, ensuring short values like 'NULL' are preserved.
  • Updated ColumnHint Structure: Modified the ColumnHint struct to include PreferredMinWidth (an integer) which replaces the previously reserved NoWrap bool field.
  • Flexible Column Floor Application: Implemented applyColumnFloors() as a shared helper that intelligently applies per-column minimum widths, using preferred minimums when space allows and gracefully degrading to a hard minimum when the budget is exceeded.
  • Reduced Hardcoded Minimum Column Width: Decreased the global minColumnWidth constant from 4 to 1, shifting the responsibility for meaningful minimums to the new data-driven NoWrapCell logic.
  • NULL Cells Wrapped as NoWrapCell: Ensured that NULL cells are now wrapped as NoWrapCell instances in spannerRowToRow() and integration tests, allowing them to benefit from the new preferred minimum width logic.
Changelog
  • internal/mycli/format/config.go
    • Added NoWrapCell struct to wrap existing Cell types and indicate content should not be wrapped.
    • Implemented WithText method for NoWrapCell to preserve wrapping when text is replaced.
    • Added IsNoWrap helper function to check if a Cell is a NoWrapCell.
  • internal/mycli/format/width.go
    • Reduced minColumnWidth constant from 4 to 1, shifting the primary minimum width enforcement to data-driven logic.
    • Introduced deriveColumnHints function to scan rows and calculate PreferredMinWidth for columns based on NoWrapCell instances.
    • Added applyColumnFloors function to apply column minimums, prioritizing PreferredMinWidth when budget allows and falling back to minColumnWidth otherwise.
    • Updated CalculateWidthWithStrategy to use deriveColumnHints.
  • internal/mycli/format/width_strategy.go
    • Modified ColumnHint struct to replace the NoWrap bool field with PreferredMinWidth int.
  • internal/mycli/format/width_strategy_greedy.go
    • Updated CalculateWidths method to accept hints []ColumnHint parameter.
    • Replaced the explicit minColumnWidth loop with a call to applyColumnFloors.
  • internal/mycli/format/width_strategy_marginal.go
    • Updated CalculateWidths method to accept hints []ColumnHint parameter.
    • Replaced the explicit minColumnWidth loop with a call to applyColumnFloors.
  • internal/mycli/format/width_strategy_proportional.go
    • Updated CalculateWidths method to accept hints []ColumnHint parameter.
    • Replaced the explicit minColumnWidth loop with a call to applyColumnFloors.
  • internal/mycli/format/width_strategy_test.go
    • Added TestStrategyRespectsPreferredMinWidth to verify strategies honor preferred minimum widths when space is ample.
    • Added TestStrategyGracefulDegradation to ensure strategies fall back to hard minimums when preferred widths exceed available space.
  • internal/mycli/format/width_test.go
    • Added TestNoWrapCell to verify the behavior of the new NoWrapCell type, including Format, RawText, IsNoWrap, and WithText.
    • Added TestDeriveColumnHints to confirm correct calculation of PreferredMinWidth from NoWrapCell instances.
    • Added TestDeriveColumnHintsNoNoWrap to ensure PreferredMinWidth remains 0 when no NoWrapCell instances are present.
  • internal/mycli/integration_test.go
    • Modified the n helper function to return a format.NoWrapCell wrapping a StyledCell for NULL values.
    • Updated paramCasesToStmtResults to wrap StyledCell for NULL values in a format.NoWrapCell.
  • internal/mycli/row_iter.go
    • Wrapped StyledCell instances for NULL values in a format.NoWrapCell when converting Spanner rows to internal format rows.
Activity
  • Gemini Code Assist provided an initial summary of the changes in the pull request.
  • github-actions[bot] posted a Code Metrics Report detailing coverage and test execution time changes.
  • apstndb requested a new summary from Gemini Code Assist.

@apstndb apstndb merged commit 88680c9 into main Mar 20, 2026
2 checks passed
@apstndb apstndb deleted the issue-567-nowrap-cell branch March 20, 2026 22:36
@apstndb apstndb mentioned this pull request Mar 22, 2026
2 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Introduce NoWrapCell to generalize minColumnWidth hardcoding

1 participant