e69b7af32aee91bcbd08e7f32b8ea78f8d3efee1
Three intertwined fixes for the no-VHI scroll path that together eliminate the 'switching to a new entry scrolls it to viewport top' behavior observed during Loading state, Loading->Ready transition window, and Tab-toggle VHI rebuild window. Cursor/viewport decoupling (the user-visible bug): * scroll_down_line / scroll_up_line no-VHI branches now advance only the cursor (cursor_line, cursor_sub_offset), then call ensure_cursor_visible_no_vhi to adjust the viewport minimally if needed. Previously they locked v_offset = cursor_line, forcing the cursor's entry to the top of the viewport on every keypress. * New helpers: advance_visual_pos, retreat_visual_pos (bounded visual-row walks using compute_visual_height), ensure_cursor_visible_no_vhi (matches the VHI-path semantics - top-align when cursor is above viewport, bottom-align with minimal scroll when below, no movement when within). * Same pattern applied to scroll_down/up_half_page and scroll_down/up_page. * scroll_to_bottom sets cursor_sub_offset to the last visual row of the last line in no-VHI state (was 0). * ensure_viewport_cache hidden anchors removed: the params-change recenter and the Loading post-check that did v_offset = cursor_line are replaced with the visibility helper. * 4 transition sites (Tab handler, ensure_visual_height_index, reload, poll VHI complete) now clamp cursor_sub_offset against the current line height instead of blindly zeroing. Width calculation correctness (root cause of the residual j/k bug): * gutter_width() pub(crate) method extracted from ui.rs's inline formula, shared between renderer and App to prevent drift. * get_content_width() now returns effective text-wrap width (area minus gutter), matching the renderer's actual_content_width. Previously it returned raw area width, causing compute_visual_height to under-count wrap rows for lines that wrapped only after gutter subtraction. * Free function gutter_width_for(total_lines, is_loading) added so handle_file_appended and reload_ready_reader can recompute width after line-count changes without conflicting borrows on self. * handle_file_appended: width now captured AFTER update_for_append (was before), so digit-boundary crossings (9->10, 99->100) don't leave stale gutter widths. ui.rs render_content now calls app.gutter_width() instead of inlining the formula (DRY). Tests: 7 existing tests that locked in the old buggy v_offset = cursor_line coupling have been rewritten to assert the new correct behavior. New property tests verify wrap_line_count matches wrap_line_chars across CJK/emoji/tab/combining-mark/control-char inputs.
Description
No description provided
1 MiB
Languages
Rust
100%