bpython linewrap is based on number of characters, causing issues with carriage returns #574

Open
iago-lito opened this Issue Nov 2, 2015 · 5 comments

Comments

Projects
None yet
2 participants
@iago-lito

Dear maintainer,

I am using BPython to run Python scripts, and I found the console output has a different behavior than the regular Python console.. For example this small snippet:

import time
for i in range(100):
    time.sleep(.1)
    print("\r{}".format(i), end="")

outputs in Python:

99                                            |
>>>                                           |

but outputs in BPython:

26                                            |
51                                            |
75                                            |
99                                            |
>>>                                           |
                                              ^ end of the console

These apparently random numbers just depend on my console width. I suspect the BPython cursor to be shifted right on each call to print even though the string starts with a \r. When it reaches the right end of the console, the current line can't be erased anymore and so a new line is started.

How should one tune / slash / fix this?

Thank you so much for BPython anyway :)

(duplicated from there)

@thomasballinger

This comment has been minimized.

Show comment
Hide comment
@thomasballinger

thomasballinger Nov 2, 2015

Member

Your explanation sounds correct - the Curtsies frontend of bpython looks at the length of the string and line-splits it based on this length. Then each of these lines are rendered separately, and each time the last carriage return and number on the line are the only thing visible.

Unfortunately this is a limitation of the current version of bpython: terminal sequences are not handled correctly, with a small number exceptions for changing text color. If you need this behavior, I suggest using bpython-curses (installed with bpython). I hope to change this eventually, and I believe features of the Blessed will make this possible in the future. Although string length calculations could be modified to change the length of a line to 0 once a \r is encountered, there aren't currently plans to do this without a more significant renderer overhaul.

Member

thomasballinger commented Nov 2, 2015

Your explanation sounds correct - the Curtsies frontend of bpython looks at the length of the string and line-splits it based on this length. Then each of these lines are rendered separately, and each time the last carriage return and number on the line are the only thing visible.

Unfortunately this is a limitation of the current version of bpython: terminal sequences are not handled correctly, with a small number exceptions for changing text color. If you need this behavior, I suggest using bpython-curses (installed with bpython). I hope to change this eventually, and I believe features of the Blessed will make this possible in the future. Although string length calculations could be modified to change the length of a line to 0 once a \r is encountered, there aren't currently plans to do this without a more significant renderer overhaul.

@iago-lito

This comment has been minimized.

Show comment
Hide comment
@iago-lito

iago-lito Nov 2, 2015

Using bpython-curses does solve the problem. Thank you for the explanation ! :)
..
Arf. Yet I liked the bpython colors and interface better. Is there a way not to have the bottom bar displaying the shortcuts in bpython-curses?

Using bpython-curses does solve the problem. Thank you for the explanation ! :)
..
Arf. Yet I liked the bpython colors and interface better. Is there a way not to have the bottom bar displaying the shortcuts in bpython-curses?

@thomasballinger

This comment has been minimized.

Show comment
Hide comment
@thomasballinger

thomasballinger Nov 2, 2015

Member

Unfortunately there is not a way to do this currently, and it probably won't be added. However the issue you described in bpython may be fixed in the medium-term future.

Member

thomasballinger commented Nov 2, 2015

Unfortunately there is not a way to do this currently, and it probably won't be added. However the issue you described in bpython may be fixed in the medium-term future.

@iago-lito

This comment has been minimized.

Show comment
Hide comment
@iago-lito

iago-lito Nov 3, 2015

Great. Thank you and good luck then :)

Great. Thank you and good luck then :)

@thomasballinger thomasballinger changed the title from Unexpected BPython console output behaviour to bpython linewrap is based on number of characters, causing issues with carriage returns Dec 17, 2015

@thomasballinger

This comment has been minimized.

Show comment
Hide comment
@thomasballinger

thomasballinger Feb 14, 2018

Member

I think this could be done by special casing carriage returns / progress bars: we can predict the length of that output by resetting to zero each \r so long as we haven't crossed a line boundary.

Discarded ideas:

  • Each time there was output we could throw it at the terminal and try to guess what happened based on cursor position - nah we don't know enough and can't find out
  • We could do output in a pty to better observe what happened, and only once a command has fully finished running do we freeze it and save it for display?
    • maybe display this pty live as the code runs?
    • or a full terminal emulator so we can hack on iterm extensions?
    • pluggable terminal backends, so you can use another of whatever you're using? (communicate with another iterm?)
Member

thomasballinger commented Feb 14, 2018

I think this could be done by special casing carriage returns / progress bars: we can predict the length of that output by resetting to zero each \r so long as we haven't crossed a line boundary.

Discarded ideas:

  • Each time there was output we could throw it at the terminal and try to guess what happened based on cursor position - nah we don't know enough and can't find out
  • We could do output in a pty to better observe what happened, and only once a command has fully finished running do we freeze it and save it for display?
    • maybe display this pty live as the code runs?
    • or a full terminal emulator so we can hack on iterm extensions?
    • pluggable terminal backends, so you can use another of whatever you're using? (communicate with another iterm?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment