fix: apply terminal semantics to carriage returns - #278
Open
Thorsrud22 wants to merge 1 commit into
Open
Thorsrud22 wants to merge 1 commit into
Thorsrud22 wants to merge 1 commit into
Conversation
A carriage return in the middle of a line (progress bars, spinners, status lines) used to end up as a line break: the CLI's stdin wrapper translated it to \n, and via the API a raw \r reached the HTML where browsers render it the same way. A terminal instead moves the cursor back to the start of the line and overwrites. Add a pre-pass that keeps only the text after the last \r on each line, treats \r\n as a plain line ending, ignores a trailing \r, and carries over escape sequences from the overwritten part so colour and link state still apply to what stays visible. The CLI now opens stdin with newline="" so the converter, not the wrapper, decides what a carriage return means. This is an approximation: a rewrite shorter than the text it replaces would leave a tail visible in a terminal, which is not reproduced. The common whole-line rewrite renders exactly as the terminal shows it. Fixes pycontribs#79
Thorsrud22
force-pushed
the
carriage-return
branch
2 times, most recently
from
September 16, 2026 18:25
bc8fa85 to
8036aae
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #79.
A carriage return in the middle of a line, which is how progress bars, spinners and status lines rewrite themselves, currently ends up as a line break. The CLI's stdin wrapper translates
\rto\n(universal newlines), and via the API a raw\rreaches the HTML, where browsers render it as a newline anyway. A terminal moves the cursor back to column 0 and overwrites.Using the example from the issue:
ONETWOTHREEEEEEFOURFIVESIX(each on its own line)ONETWOFIVESIXChange
apply_regexkeeps only the text after the last\ron each line.\r\nis treated as a plain line ending and a trailing\ris ignored.ESC[32m[###] 30%\r[######] 100%ESC[0mrenders as a green[######] 100%, and a hyperlink that is still open when the line is rewritten applies to the new text. A link whose text was wholly overwritten is dropped rather than left as an empty anchor.newline=""so carriage returns reach the converter untranslated. CRLF input still produces the same output as before.Known approximation, stated in the docstring too: when the rewritten text is shorter than what it replaces, a real terminal would still show the tail of the old text (
THREEEEEE\rFOURshowsFOUREEEEE). This PR showsFOUR. Reproducing the tail would need per-column tracking of characters and their styles, which is a much bigger change; the whole-line rewrite that progress bars do is rendered exactly as the terminal shows it. Happy to go the "document it" route from the issue instead if you'd rather not change behaviour.Verification