Skip to content

fix(read): --max-lines N returns N lines, not N/2 - #3678

Closed
dwin-gharibi wants to merge 1 commit into
rtk-ai:developfrom
dwin-gharibi:fix/read-max-lines-halves-output
Closed

dwin-gharibi wants to merge 1 commit into
rtk-ai:developfrom
dwin-gharibi:fix/read-max-lines-halves-output

Conversation

@dwin-gharibi

Copy link
Copy Markdown

Closes #3677.

Summary

  • --max-lines N now returns the first N lines, symmetric with --tail-lines N returning the
    last N. It previously routed through filter::smart_truncate, whose ordinary-line budget is
    max_lines / 2, so head -20 file — which rewrites to --max-lines 20 — returned 10 lines
    of a plain text file.
  • Removed filter::smart_truncate and its four tests. This was its only production caller, and
    the halving is its documented behaviour ("Non-important lines beyond max_lines/2 are silently
    skipped"), so leaving it would leave a loaded gun for the next caller.

Test plan

  • cargo fmt --all && cargo clippy --all-targets && cargo test
  • Manual testing: rtk <command> output inspected

Unit tests (added, TDD — red before green)

src/cmds/system/read.rs:

  • max_lines_returns_the_first_n_lines — for N in 5/10/20/50 the window is exactly N lines,
    starting at line 1 and contiguous. Red on develop:
    --max-lines 5 must return 5 lines, got 3.
  • max_lines_under_the_limit_is_untouched.
  • tail_lines_still_returns_the_last_n_lines — control; passes before and after.

One existing test updated

test_apply_line_window_max_lines_still_works asserted output.contains("more lines"), pinning
smart_truncate's marker. It now asserts the head contract exactly ("a\nb\n", no marker) —
see the note below.

Behavioural check against real head

head -n N rtk read --max-lines N before after
N=5 5 lines 2 5, byte-identical
N=10 10 lines 5 10, byte-identical
N=20 20 lines 10 20, byte-identical
N=50 50 lines 25 50, byte-identical
source file, N=10/30 partial byte-identical

Controls: --tail-lines 20 still equals tail -n 20; a full rtk read still equals cat.

Suite

cargo test --all: 2624 passed, 0 failed. (2625 on develop; net −1 is +3 added, −4 removed with
smart_truncate.)
cargo clippy --all-targets: clean. cargo fmt --all: clean.

The hook rewrites head -N file to rtk read file --max-lines N, and that
path called filter::smart_truncate, whose budget for ordinary lines is
max_lines / 2. For any file without 'important' lines -- plain text, logs,
CSV, data -- the result was exactly half the requested size with nothing
to say the rest was dropped: head -20 f.txt returned 10 lines.

Source files hid it, because braces, pub, export and imports count as
important and are kept past the half budget, and the existing fixtures are
code.

Slice the first N lines instead, symmetric with --tail-lines N slicing the
last N. No truncation marker: this window is one the caller asked for, and
head prints none, so a marker would make the rewrite differ from the
command it replaces.

smart_truncate had exactly one production caller and the halving is its
documented behaviour, so it goes with it rather than waiting for the next
caller to inherit the same surprise.
Copilot AI lite review requested due to automatic review settings August 23, 2026 18:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@KuSh

KuSh commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Thanks for the detailed writeup and the comparison table against real head. #3941, merged on 2026-09-13, fixed the reported behaviour a different way: head -N now rewrites to a new --head-lines N window that slices at newline byte offsets and returns exactly N lines, while --max-lines is kept on purpose as a structural preview and is documented as such in src/main.rs. Because apply_line_window now takes a head_lines argument and the byte windows sit beside it, the change to --max-lines here and the removal of smart_truncate no longer apply, and the zero-length guard you added is already present. If a case from your table is still wrong on the current develop, please comment here or reopen.

@KuSh KuSh closed this Sep 19, 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.

head -20 file returns 10 lines

3 participants