Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

clear doesn't take effect immediately on Linux #2284

Closed
belliriccardo opened this issue May 12, 2022 · 5 comments · Fixed by #2286
Closed

clear doesn't take effect immediately on Linux #2284

belliriccardo opened this issue May 12, 2022 · 5 comments · Fixed by #2286
Milestone

Comments

@belliriccardo
Copy link
Contributor

belliriccardo commented May 12, 2022

Hi! I'm writing a small script and I'm using click for user input and console text formatting. In practice, I use the click.getchar() function to read a single char from stdin, and do some processing from there; I construct a string representing a visual representation of the output and I print it. But! Whenever I use click.clear() instead of os.system('clear'), I get an inconsistent behavior: the terminal doesn't get cleared at the beginning of the script,

Here is a minimal reproducible example (imports omitted for brevity): script1.py

def main():
    os.system('clear')
    c = click.getchar()

if __name__ == '__main__':
    main()

python3 script1.py -> the terminal gets cleared and there's only the blinking cursor; this is the expected behavior. Instead, here's script2.py:

def main():
    click.clear()
    c = click.getchar()

if __name__ == '__main__':
    main()

python3 script2.py -> see: image

The terminal doesn't get cleared, I can still see my username, the command, etc. Obviously this is trivial to circumvent; my implementation is:

def clearscreen(use_click=False):
    click.clear() if use_click else os.system('cls' if os.name == 'nt' else 'clear')

Something like this could be mainlined in click.clear(), for example something like (taking from the current implementation):

def clear(scroll: bool = True) -> None:
    if not isatty(sys.stdout):
        return
    if WIN:
        os.system("cls")
    else:
        sys.stdout.write("\033[2J\033[1;1H") if scroll else os.system("clear")

Obviously the default value would follow the current behavior for consistency. I hope I've been thorough enough. Thanks!

  • OS: Ubuntu 22.04
  • Python version: 3.10.4
  • Click version: 8.0.3
@belliriccardo belliriccardo changed the title add the option to click.clear() to use "clear" instead of printing "\033[2J\033[1;1H" add the option to click.clear() to use "clear" instead of printing "\033[2J\033[1;1H" on linux May 12, 2022
@davidism
Copy link
Member

Using click.echo instead of sys.stdin.write ensures that the control code is flushed and takes effect before the next terminal interaction. Until a fix is released, you can manually do sys.stdout.flush() after click.clear().

Also, there's no need for the if WIN section anymore. Colorama is always required on Windows now, and it handles the ANSI clear all code.

@belliriccardo
Copy link
Contributor Author

Yes I was thinking it had to do something with the flushing of the buffer. The last snippet of code I pasted was modified from click.clear(), maybe it can be rearranged with your suggestions like:

def clear() -> None:
    if not isatty(sys.stdout):
        return
    echo("\033[2J\033[1;1H", nl=False)

What do you think?

@davidism
Copy link
Member

Yes, I tried that earlier on Linux and Windows and it worked. You're welcome to make a PR, or I will later.

@belliriccardo
Copy link
Contributor Author

belliriccardo commented May 12, 2022

If it's not urgent I'll do it in a few hours (tomorrow)

belliriccardo added a commit to belliriccardo/click that referenced this issue May 13, 2022
@belliriccardo
Copy link
Contributor Author

PR #2286 should be good to go! Sorry I made another one and then closed it, it's my first PR to a public repo, I wanted to update it again to let it pass all the checks.

@davidism davidism changed the title add the option to click.clear() to use "clear" instead of printing "\033[2J\033[1;1H" on linux clear doesn't take effect immediately on Linux May 13, 2022
@davidism davidism added this to the 8.1.4 milestone Jun 30, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 15, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants