Skip to content

fix: fixed tui log rendering and scroll behavior#264

Merged
jdx merged 5 commits intojdx:mainfrom
dimmyjing:fix/tui-log-scroll
Mar 2, 2026
Merged

fix: fixed tui log rendering and scroll behavior#264
jdx merged 5 commits intojdx:mainfrom
dimmyjing:fix/tui-log-scroll

Conversation

@dimmyjing
Copy link
Contributor

The scroll behavior is actually not as simple to fix as I thought. The main observation is that there really isn't any good way to retrieve the number of lines the log renderer will take after wrapping. There is a feature within ratatui to enable getting number of lines that will be rendered, but it is unstable for now. Although the log viewer works a lot better with it enabled.

This PR changes the meaning of log_scroll. In the past, log_scroll represents the beginning of the log buffer that will be rendered to the screen, but text wrapping made it such that lines can be hidden below the display buffer. In this PR, log_scroll represents the line number of the last displayed line in the buffer instead, while using Paragraph::line_count (the unstable feature) to scroll to the bottom instead.

This PR also adds a function to clean the logs of the tab character and the clear screen ansi code. I expect more to be added in the future, but these are the two main ones that are breaking the log panel in my testing.

@gemini-code-assist
Copy link

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 addresses and resolves issues related to log rendering and scrolling within the TUI. By leveraging an unstable ratatui feature for accurate line counting and redefining the log_scroll mechanism, the log viewer now provides a more reliable and intuitive user experience, particularly when dealing with text wrapping and problematic log content. Additionally, it introduces a cleaning mechanism for log lines to prevent display glitches caused by special characters.

Highlights

  • Improved Log Scrolling: The log_scroll variable now represents the line number of the last displayed line in the log buffer, rather than the first. This change, combined with the use of ratatui's unstable line_count feature, significantly enhances the accuracy of log scrolling, especially with text wrapping.
  • Enhanced Log Rendering: A new clean_log_line function has been introduced to preprocess log entries, removing problematic characters like tab ( ) and ANSI clear screen codes (�[2J), which previously caused rendering issues in the TUI log panel.
  • Ratatui Unstable Feature Enabled: The unstable-rendered-line-info feature has been enabled for the ratatui dependency, allowing the application to accurately determine the number of lines a Paragraph widget will render after text wrapping, which is crucial for correct scroll behavior.
  • Refined Scroll Logic: Various log scrolling functions (e.g., toggle_log_follow, scroll_logs_down, scroll_logs_page_down, update_logs, and 'G' keybind) have been updated to align with the new log_scroll meaning, ensuring consistent and correct log navigation.
Changelog
  • Cargo.toml
    • Enabled the unstable-rendered-line-info feature for the ratatui dependency.
  • src/tui/app.rs
    • Modified the sorting method for fuzzy search results from sort_by to sort_by_key for improved clarity.
    • Adjusted log_scroll calculation in toggle_log_follow to set it to the full content length when following logs.
    • Updated max_scroll calculation in scroll_logs_down and scroll_logs_page_down to use the full content length.
    • Simplified update_logs scroll logic to set log_scroll directly to log_content.len() for follow mode and initial load.
  • src/tui/event.rs
    • Modified the log_scroll calculation when jumping to the bottom of logs via the 'G' keybind to use the full content length.
  • src/tui/ui.rs
    • Added LOG_VIEWPORT_MAX_LINES constant to control the number of log lines rendered in the viewport.
    • Implemented log_skip and log_take logic for rendering a limited window of log lines around the scroll position.
    • Added padding to visible_lines to maintain a consistent viewport size when fewer lines are available.
    • Introduced clean_log_line function to remove ANSI clear screen codes and replace tab characters with spaces.
    • Integrated clean_log_line into the log rendering pipeline to preprocess log entries.
    • Utilized Paragraph::line_count for precise scroll positioning based on rendered lines.
    • Modified scrollbar state initialization to use total_lines directly for accurate representation.
    • Updated highlight_log_line function signature to accept String instead of &str to accommodate cleaned log lines.
Activity
  • No human activity (comments, reviews) has been recorded on this pull request yet.
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.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

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.

Copy link

@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 refactors the TUI log rendering and scrolling behavior, notably by changing the semantics of log_scroll and leveraging an unstable ratatui feature for better line wrapping calculations. It also introduces a utility to clean log lines. The changes are generally well-implemented, but I've identified a regression in the search result sorting logic that needs to be addressed. I've also included a suggestion to optimize the new log cleaning function for better performance.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Greptile Summary

This PR refactors the TUI log rendering to fix scroll behavior by changing log_scroll semantics from "beginning of buffer" to "last displayed line number". It also adds log cleaning (removes tab chars and clear screen ANSI codes) and enables ratatui's unstable line counting feature.

Major changes:

  • Enabled unstable-rendered-line-info feature in ratatui for accurate line counting after text wrapping
  • Changed log_scroll to represent the last displayed line instead of buffer start position
  • Added clean_log_line() function to sanitize log output
  • Fixed fuzzy search sorting to properly order by descending score
  • Introduced LOG_VIEWPORT_MAX_LINES constant (100 lines) for viewport management

Critical issues found:

  • Integer underflow bug in scroll calculation that will cause panics in debug builds
  • The 'g' key (scroll to top) sets log_scroll=0 which only displays 1 line instead of a full viewport due to the new semantics

Confidence Score: 1/5

  • Critical bugs present that will cause runtime panics and incorrect behavior
  • Two critical logic errors: (1) integer underflow in scroll calculation will panic in debug builds or produce incorrect behavior in release mode, and (2) scroll-to-top functionality is broken, showing only 1 line instead of a full viewport. These bugs significantly impact core functionality.
  • Pay close attention to src/tui/ui.rs (line 914 underflow) and src/tui/event.rs (line 413 scroll behavior)

Important Files Changed

Filename Overview
Cargo.toml Enabled unstable ratatui feature for rendered line info to support line counting after text wrapping
src/tui/app.rs Updated fuzzy search sorting and simplified log_scroll calculations to match new semantics (last displayed line)
src/tui/event.rs Updated 'G' key handler for new log_scroll semantics, but 'g' key sets log_scroll=0 which causes display issue
src/tui/ui.rs Refactored log rendering with new scroll semantics and log cleaning, but has critical integer underflow bug

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    Start[Log Rendering] --> CheckFollow{log_follow enabled?}
    CheckFollow -->|Yes| SetToEnd[Set log_scroll = log_content.len]
    CheckFollow -->|No| CheckScroll[Use current log_scroll]
    
    SetToEnd --> CalcWindow[Calculate viewport window]
    CheckScroll --> CalcWindow
    
    CalcWindow --> Skip[log_skip = log_scroll - LOG_VIEWPORT_MAX_LINES]
    Skip --> Take[log_take = min log_scroll, LOG_VIEWPORT_MAX_LINES]
    Take --> GetLines[Get lines from buffer: skip log_skip, take log_take]
    
    GetLines --> Clean[Clean log lines: remove tabs, ANSI codes]
    Clean --> Highlight[Apply syntax highlighting and search matches]
    Highlight --> Pad{lines < LOG_VIEWPORT_MAX_LINES?}
    
    Pad -->|Yes| AddPadding[Add empty lines to reach LOG_VIEWPORT_MAX_LINES]
    Pad -->|No| CreateParagraph[Create Paragraph widget]
    AddPadding --> CreateParagraph
    
    CreateParagraph --> CountLines[Calculate line_count with text wrapping]
    CountLines --> CalcScroll[scroll_offset = line_count - area.height ⚠️ underflow risk]
    CalcScroll --> Render[Render widget with scroll offset]
    Render --> End[Display logs]
Loading

Last reviewed commit: ea29b5a

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

4 files reviewed, 4 comments

Edit Code Review Agent Settings | Greptile

@jdx
Copy link
Owner

jdx commented Mar 2, 2026

@greptileai

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 2, 2026

Additional Comments (1)

src/tui/event.rs
With the new log_scroll semantics (last displayed line), setting to 0 causes only 1 line to be shown due to clamp(1, LOG_VIEWPORT_MAX_LINES) in ui.rs. Should probably be min(LOG_VIEWPORT_MAX_LINES, app.log_content.len()) to show a full viewport at the top.

@dimmyjing
Copy link
Contributor Author

log_scroll should have a minimum of 1, because otherwise it's possible for the top of the viewport to not be shown either for the same reason why the bottom was hidden in the previous implementation.

@jdx jdx merged commit 49ee402 into jdx:main Mar 2, 2026
4 checks passed
@jdx jdx mentioned this pull request Mar 2, 2026
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.

2 participants