Skip to content

fix: goto a fractional line lands one wrapping line too high - #1154

Merged
noborus merged 2 commits into
noborus:masterfrom
VXNCXNX:fix/goline-fractional-rounding
Aug 17, 2026
Merged

fix: goto a fractional line lands one wrapping line too high#1154
noborus merged 2 commits into
noborus:masterfrom
VXNCXNX:fix/goline-fractional-rounding

Conversation

@VXNCXNX

@VXNCXNX VXNCXNX commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

In wrap mode, g then 3.4 moves to 3.3.

Five lines of 800 characters, 80x25 terminal, ov -w:

before: /tmp/wrap.txt:Moved to line 3.3    (3/5)
after:  /tmp/wrap.txt:Moved to line 3.4    (3/5)

Cause

goLine truncates the fractional part:

nTh := int(fractionalPart * 10)

float64 cannot represent 3.4 exactly, so math.Modf returns 0.3999... and * 10 gives 3.99..., which truncates to 3. The same happens for 3.3, 3.8 and 10.7:

3.1 -> trunc=1  round=1
3.3 -> trunc=2  round=3
3.4 -> trunc=3  round=4
3.5 -> trunc=5  round=5
3.8 -> trunc=7  round=8
10.7 -> trunc=6 round=7

Roughly half the single digits are wrong, and the wrong ones are silently off by one rather than failing.

The fix

math.Round instead of truncation, clamped to 9 since the fractional part is a single digit. nTh == 0 still takes the existing whole-line branch, so g 3 is unchanged.

Verification

TestRoot_goLineNth in oviewer/action_test.go walks 3.1 through 3.9 and asserts both the status message and topLX, so it pins the actual scroll position rather than only the label.

Reverting just the expression fails it:

--- FAIL: TestRoot_goLineNth
    goLine("3.3") message = "Moved to line 3.2", want "Moved to line 3.3"
    goLine("3.3") topLX = 160, want 240
    goLine("3.4") message = "Moved to line 3.3", want "Moved to line 3.4"
    goLine("3.4") topLX = 240, want 320

go build ./..., go vet ./..., gofmt -l and go test ./... are all clean.

Disclosure: written with AI assistance (Claude Code). I reproduced the off-by-one in a real terminal via tmux against binaries built before and after, checked the float behaviour in a standalone program, and ran the mutation check myself.

int(fractionalPart * 10) truncates, and float64 cannot represent 3.4
exactly, so 3.4 - 3 is 0.3999... and truncates to 3. Round instead,
clamped to a single digit.
Windows cannot remove the temp file while the reader still holds it open,
which failed the TempDir cleanup in CI.
@noborus

noborus commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Thank you. That is indeed better.

@noborus
noborus merged commit 072af71 into noborus:master Aug 17, 2026
6 checks passed
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