CITGuru / PyInquirer

A Python module for common interactive command line user interfaces
MIT License
1.91k stars 235 forks source link

Exit with KeyboardInterrupt messes up terminal #120

Open ewels opened 3 years ago

ewels commented 3 years ago

Hi there,

Many thanks for merging the recent PRs. We're currently using the master branch until a release goes out so I noticed the updates pretty quickly. After patching our code to use the new prompt.prompt() syntax everything seems to work, however we get one nasty problem:

If, during a prompt, the user hits ctrl-c to cancel, the terminal is not restored to it's previous state. This means that even after exiting the script, terminal behaviour is messed up. Scrolling, clicking and using the cursor keys no longer behave normally, typing works but is hidden from the prompt so invisible, and hitting enter no longer gives newlines. As such, the current terminal session is basically bricked. This behaviour is the same with or without raise_keyboard_interrupt=True.

I assume that this is related to the switch to prompt_toolkit 3.0 by @jonathanslenders in #118. Any ideas how we can handle this properly to return the terminal to normal upon interruption?

Many thanks,

Phil

ewels commented 3 years ago

I guess that we need to call reset() when the KeyboardInterrupt is caught and maybe also on the buffer? I'm not super clear on what this should be called on though...

CITGuru commented 3 years ago

@ewels I tried to get this same scenario, but on my end both Mac OS X Sierra and Windows 10, I don't seem to notice this issue.

ewels commented 3 years ago

Ah strange 😕 I was going to try to make a minimal example for you to make sure that it's not something odd with the way that I'm using the library, but I see the same behaviour with an unmodified list.py from the examples:

Jul-10-2020 09-30-49

(You can't see me type foo on the prompt, hitting enter doesn't give newlines)

I just tried with a totally fresh conda environment with Python 3.8 to check that it's not a package conflict or old versions of anything and I still get the same:

$ (base)  ~/.../PyInquirer_terminal_issue » conda create --name pyinquirer python=3.8
Collecting package metadata (repodata.json): done
Solving environment: done

## Package Plan ##

  environment location: /Users/philewels/miniconda2/envs/pyinquirer

  added / updated specs:
    - python=3.8

The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    certifi-2020.6.20          |   py38h32f6830_0         151 KB  conda-forge
    pip-20.1.1                 |             py_1         1.1 MB  conda-forge
    python-3.8.3               |cpython_hd5f0129_0        31.7 MB  conda-forge
    python_abi-3.8             |           1_cp38           4 KB  conda-forge
    readline-8.0               |       hed1e85f_1         255 KB  conda-forge
    setuptools-49.1.0          |   py38h32f6830_0         918 KB  conda-forge
    sqlite-3.32.3              |       h93121df_1         1.7 MB  conda-forge
    xz-5.2.5                   |       h0b31af3_1         227 KB  conda-forge
    ------------------------------------------------------------
                                           Total:        36.0 MB

The following NEW packages will be INSTALLED:

  ca-certificates    conda-forge/osx-64::ca-certificates-2020.6.20-hecda079_0
  certifi            conda-forge/osx-64::certifi-2020.6.20-py38h32f6830_0
  libcxx             conda-forge/osx-64::libcxx-10.0.0-h1af66ff_2
  libffi             conda-forge/osx-64::libffi-3.2.1-h4a8c4bd_1007
  ncurses            conda-forge/osx-64::ncurses-6.1-h0a44026_1002
  openssl            conda-forge/osx-64::openssl-1.1.1g-h0b31af3_0
  pip                conda-forge/noarch::pip-20.1.1-py_1
  python             conda-forge/osx-64::python-3.8.3-cpython_hd5f0129_0
  python_abi         conda-forge/osx-64::python_abi-3.8-1_cp38
  readline           conda-forge/osx-64::readline-8.0-hed1e85f_1
  setuptools         conda-forge/osx-64::setuptools-49.1.0-py38h32f6830_0
  sqlite             conda-forge/osx-64::sqlite-3.32.3-h93121df_1
  tk                 conda-forge/osx-64::tk-8.6.10-hbbe82c9_0
  wheel              conda-forge/noarch::wheel-0.34.2-py_1
  xz                 conda-forge/osx-64::xz-5.2.5-h0b31af3_1
  zlib               conda-forge/osx-64::zlib-1.2.11-h0b31af3_1006

Proceed ([y]/n)? y

Downloading and Extracting Packages
pip-20.1.1           | 1.1 MB    | ######################################################################################################################### | 100%
xz-5.2.5             | 227 KB    | ######################################################################################################################### | 100%
readline-8.0         | 255 KB    | ######################################################################################################################### | 100%
setuptools-49.1.0    | 918 KB    | ######################################################################################################################### | 100%
python-3.8.3         | 31.7 MB   | ######################################################################################################################### | 100%
python_abi-3.8       | 4 KB      | ######################################################################################################################### | 100%
sqlite-3.32.3        | 1.7 MB    | ######################################################################################################################### | 100%
certifi-2020.6.20    | 151 KB    | ######################################################################################################################### | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
 #
 # To activate this environment, use
 #
 #     $ conda activate pyinquirer
 #
 # To deactivate an active environment, use
 #
 #     $ conda deactivate

$ (base)  ~/.../PyInquirer_terminal_issue » conda activate pyinquirer
(pyinquirer)  ~/.../PyInquirer_terminal_issue » pip install git+ssh://git@github.com/CITGuru/PyInquirer.git@master#egg=PyInquirer
Collecting PyInquirer
  Cloning ssh://****@github.com/CITGuru/PyInquirer.git (to revision master) to /private/var/folders/tk/k7tjvpqs0tbfd0bzvt4htrzh0000gn/T/pip-install-1i0hfvqj/PyInquirer
  Running command git clone -q 'ssh://****@github.com/CITGuru/PyInquirer.git' /private/var/folders/tk/k7tjvpqs0tbfd0bzvt4htrzh0000gn/T/pip-install-1i0hfvqj/PyInquirer
Collecting prompt_toolkit<3.1.0,>=3.0.0
  Using cached prompt_toolkit-3.0.5-py3-none-any.whl (351 kB)
Collecting Pygments>=2.2.0
  Using cached Pygments-2.6.1-py3-none-any.whl (914 kB)
Collecting wcwidth
  Downloading wcwidth-0.2.5-py2.py3-none-any.whl (30 kB)
Building wheels for collected packages: PyInquirer
  Building wheel for PyInquirer (setup.py) ... done
  Created wheel for PyInquirer: filename=PyInquirer-1.0.3-py3-none-any.whl size=27889 sha256=ced90073463e5ec930861848bc1fd7414f5467deb7d7d8aa4c234d430a52c48e
  Stored in directory: /private/var/folders/tk/k7tjvpqs0tbfd0bzvt4htrzh0000gn/T/pip-ephem-wheel-cache-aybkl_xi/wheels/da/92/5b/84b59d286616e4738c9f8ea67bc1acf18a22c9f39559aced0d
Successfully built PyInquirer
Installing collected packages: wcwidth, prompt-toolkit, Pygments, PyInquirer
Successfully installed PyInquirer-1.0.3 Pygments-2.6.1 prompt-toolkit-3.0.5 wcwidth-0.2.5

$ (pyinquirer)  ~/.../PyInquirer_terminal_issue » pip freeze
certifi==2020.6.20
prompt-toolkit==3.0.5
Pygments==2.6.1
PyInquirer @ git+ssh://git@github.com/CITGuru/PyInquirer.git@7485a1fd5442332399d5f05c84e4fd74b63a5823
wcwidth==0.2.5

$ (pyinquirer)  ~/.../PyInquirer_terminal_issue » python list.py
? What do you want to do?  Make a reservation
? What size do you need?  Standard
? Which vehicle you want to use for delivery?  (Use arrow keys)
Cancelled by user
   car
{} truck

$ (pyinquirer)  ~/.../PyInquirer_terminal_issue » -bash: kjsdbfkjsdbf: command not found
$ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue » $ (pyinquirer)  ~/.../PyInquirer_terminal_issue »