-
Notifications
You must be signed in to change notification settings - Fork 127
Migrate from using readline to prompt-toolkit #1553
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
base: main
Are you sure you want to change the base?
Conversation
Tons of tests failing and some even getting stuck.
…f the correct arguments to app.complete() This fixes all of the test_argparse_comleter.py tests. There are still failing tests in test_cmd2.py, test_history.py, and test_run_pyscript.py as well as a test in test_cmd2.py that gets stuck.
TODO: - prompt-toolkit history isn't properly initialized with history from a persistent history file, as shown by the remaining failing history test
… of mocking the built-in input function. There are still 3 failing and 1 skipped test in test_cmd2.py Additionally, some tests in test_run_pyscript.py are getting stuck.All tests in other files are passing.
…ork with prompt-toolkit
Also: - Fixed make clean so it cleans up code coverage file artifacts
Also added a bottom toolboar for displaying these type hints.
|
🤖 Hi @tleonhardt, I've received your request, and I'm working on it now! You can track my progress in the logs for more details. |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #1553 +/- ##
==========================================
+ Coverage 98.94% 99.17% +0.22%
==========================================
Files 21 21
Lines 4942 4940 -2
==========================================
+ Hits 4890 4899 +9
+ Misses 52 41 -11
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
|
🤖 I'm sorry @tleonhardt, but I was unable to process your request. Please see the logs for more details. |
… PromptSession and ensuring consistent input/output usage
…rs for better compatibility
…ws runners for better compatibility" This reverts commit 59c5ffa.
Split the try/except block in 'ppaged' to handle 'ImportError' for 'termios' separately. This prevents 'UnboundLocalError' when accessing 'termios.error' in the 'except' clause on platforms where 'termios' is not available (like Windows).
Replaced 'threading.RLock' 'terminal_lock' with 'asyncio.call_soon_threadsafe' and 'self._in_prompt' flag for 'async_alert'. Updated 'examples/async_printing.py' to remove lock usage. Updated tests to mock event loop and '_in_prompt' state.
Updated 'examples/async_printing.py' to use 'asyncio' tasks and 'create_background_task' instead of 'threading'. Added 'pre_prompt' hook to 'cmd2.Cmd' and integrated it into 'read_input' to support starting background tasks when the prompt loop starts.
Correctly initialize a new PromptSession with pipe_input in the test to avoid AttributeError since the 'input' property is read-only.
Also: - Move where pre_prompt is defined so it is near other hook methods - Document pre_prompt hook in Hooks feature docuemntation
This defaults to the columnar way. But a user can set it to CompleteStyle.READLINE_LIKE to get readline style tab completion. Also: - Renamed `include_bottom_toolbar` flag to just `bottom_toolbar` - Renamed `_bottom_toolbar` method to `get_bottom_toolbar` which is a better name for it - Updated `examples/hello_cmd2.py` to use readline style tab-completion
- Added max_column_completion_items setting (default 7) to configure the threshold. - Updated Cmd.complete to switch between CompleteStyle.COLUMN and CompleteStyle.MULTI_COLUMN. - Added test case to verify the behavior.
Also: - Disable dynamic complete_style switching when READLINE_LIKE is specified
…n LibEdit was insalled instead of readline
Hoping to clear up some type errors on windows
Also: - Add test for get_bottom_toolbar with a very narrow terminal
|
These are some observations / thoughts I had. I hope these are helpful! 1 Uncancelled Tasks
I changed 2 Thread Unclosed
Updating
Minor thing... might be worth keeping a refcount to the global thread var, and closing the thread when the (or all) cmd2 objects quit? 3 AnyIOWhen writing async python in the past, I have preferred the use of anyio. Not sure if it is helpful, but this page is at least worth a read / being aware of. Its a small lib. They solve some edge cases that can arise when using asyncio, especially around cancellation. |
…sks on interrupt Also: - Added return param to a docstring
|
@notnotbrandon Thanks for the feedback on the new I fixed the problem with uncancelled async tasks when an async There is only ever 1 thread created for the async commands and it is a daemon thread. The main thread will automatically clean it up when it is ready to exit. So I'm not worried about that. I don't think we want to add any extra dependencies on |
Since prompt-toolkit has all of the components for full screen applications built into it, I thought it would be interesting to demonstrate how users can configure their own custom key bindings to trigger a background method on keypress that prints a message above the prompt. This has some limitations at the moment in that it only works while the prompt is being displayed. But its a start to building a more interesting example.



This PR migrates from using GNU Readline for user input, tab-completion, and history to using prompt-toolkit for the same purpose.
prompt-toolkitis a pure-Pythonreadlinereplacement that is fully cross-platform compatible and doesn't rely on the presence of underlying C dynamic libraries. It also opens the door to some advanced features in the future.All use of
readlineis removed and thecmd2.rl_utilsmodule has been deleted. There is a newcmd2.pt_utilsmodule in its place. Currently all linting is passing and the documentation builds. This is essentially final draft that needs more testing. There are likely a some things that need to be considered related to asynicio support, signal handlers, and blocking popen calls.All tests are passing on all platforms. I have done some manual testing on both macOS and Linux. But I don't have a Windows VM to do any manual testing on Windows however.
NOTE FOR REVIEWERS: The substantive code changes are in the 3 following files (all in the
cmd2directory):argparse_completer.py(modified)cmd2.py(modified)pt_utils.py(new)TODO:
alias create <TAB>- currently showing nothinggetting_started.pyexample to show how to use the optional bottom toolbar featurecmd2.Cmd.read_inputwork like they did previously - test usingexamples/read_input.py<Ctrl>+cworks for SIGINT when usingshellcommand - need to fix how prompt is redrawn afterppaged(get traceback with termios.error)ppagedworks properly like it did before - works, but doesn't handle SIGKILL correctly - get tracebackCompleteStyle.COLUMNtoCompleteStyle.MULTI_COLUMNwhen there are a lot of completions - based on a settable which defaults to 7; switching disabled when user specifiesREADLINE_LIKEstylepyandipyshellsselfstill works correctly inipyselfstill work correctly inpypyshell for systems withLibEditself._in_prompt- I added athreadling.lockobject to protect access toself._in_promptto be safeprompt-toolkitnatively usesasycnioand starts an event loopexamples/async_call.pyexample to account forprompt-toolkitstarting anasyncioevent loopasyncioto replace things likeself.terminal_lock,async_alert, andasync_update_prompt- removedself.terminal_lockand updatedsync_alert, and other stuff as well asasync_printing.pyexample; also removed unusedasync_refresh_promptandneed_prompt_refreshmethodsprompt-toolkitneeds to run in the main thread for various reasons, though it does have good support for handling backkground tasks in other threadsdo_*commands is inexamples/async_commands.py- if we are happy with it, we can move the decorator there intocmd2/decorators.pyand the utility function intocmd2.utils.pyand add some unit testsCHANGELOG.mdand in the Zensical documentation