Repository navigation
cmd2 4.0 discussion #1538
Copy link
Copy link
Closed
Labels
Milestone
Description
Now that cmd2 3.0.0 is out, it's time to start discussing what we would like to see in the 4.0.0 release for cmd2.
Features @kmvanbrunt and I have discussed for 4.x include:
- Remove explicit dependency on Python's built-in
cmdmodule, but retain backwards compatibility (PR Remove dependency on Python's built-in cmd module #1539) - Replace dependency on
twinefor publishing PyPI package with one onuv publish(Use uv for publishing to PyPI instead of twine #1548) - Replace use of
invokewith use ofmake, primarily used for cleanup at this point (Add clean target to Makefile that runs what is in invoke clean #1549) - Migrate documentation to Zensical which is essentially MkDocs 2.0, but implemented in Rust and much faster (PR Migrate documentation to use Zensical instead of MkDocs #1557)
- Remove dependency on Python's built-in
readlinemodule and replace it with a dependency on prompt-toolkit which is a pure Python replacement for GNU Readline (PR Migrate from using readline to prompt-toolkit #1553)- Support adding a bottom toolbar to display real-time status via
prompt-toolkit(PR Migrate from using readline to prompt-toolkit #1553) - Add
prompt-toolkitsyntax highlighting of text entered by users, at least for command names (PR Migrate from using readline to prompt-toolkit #1553) - Add support for
prompt-toolkitInput Validation - I looked into this and honestly if we add support for more advanced input validation, I would prefer to add a dependency onpydanticand go that route. But that is more than I want to bite off for the 4.0 release ofcmd2. - Add auto-suggestions using
prompt-toolkitsimilar to fish-shell where it will show a recommended completion grayed-out per user request in Add auto suggestion feature #1545 (PR Migrate from using readline to prompt-toolkit #1553)
- Support adding a bottom toolbar to display real-time status via
- Handle
prompt-toolkitcompletion edge cases related to adding quotes (PR Refactor completion API #1575) - Consider implementing syntax that is essentially compatible with Typer for defining command arguments based on type hints. A user documented how to do this in Discussion A plugin for Typer command define within cmd2 #1530.
- For this I envision something like a
@cmd2.typerdecorator that will auto-generate anargparse.ArgumentParserbased on argument annotations - We won't be tackling this in the 4.0.0 release unless someone else wants to do the work
- For this I envision something like a
- Remove the transcript testing feature set (PR Remove the Transcript Testing feature #1583)
- Investigate migrating type-checking from
mypyto ty now thattyis in beta- Will revisit this in the future after releasing 4.0.0. This isn't a backwards incompatible change for anyone and I'd like to wait for this library to mature a little more before migrating to it
- Replace restrictive type hints (e.g.
list) with broader ones likeSequenceorIterable(PR Use more generic types where possible for input parameters #1584) - Ensure examples all work
- Change async alert methods to rely on a queue (PR Refactored async alerts. #1586)
- Remove the
default_to_shellflag since it can result in unintended execution which can be dangerous (PR Removed default_to_shell. #1590) - Restore concatenating all lines of a multi-line command into one for the up-arrow history (PR Switch to using prompt-toolkit's multiline filtering. #1589)
- Fix
Cmd2Lexercoloring of command names used on continued lines in multiline commands (PR Fixed multiline command highlighting in Cmd2Lexer #1591) - Ensure documentation and CHANGELOG are fully up to date
Moving to prompt-toolkit and no longer depending on cmd will be a large paradigm shift for cmd2. But this will open doors for easier and more consistent cross-platform support as well as being able to provide some more advanced features that we cannot now.
Reactions are currently unavailable
Activity
tleonhardt commentedon Dec 7, 2025
PR #1539 handles removing the explicit dependency on Python's built-in
cmdmoduletleonhardt commentedon Dec 12, 2025
I plan to educate myself on
Zensicalover the holidays.I think @kmvanbrunt has already started looking into
prompt-toolkit.@theagilehacker @joqual If you would like to help with anything here, we'd love some more developers to get involved. Also if you have ideas for what you would like to see in
cmd2, please suggest them. Most of the planned work requires replacingreadlinewithprompt-toolkitfirst. But theTyperstuff is fully independent of that. I suspect Kevin wouldn't mind help withprompt-tookitwork, so familiarizing yourself with that also would be helpful.tleonhardt commentedon Dec 22, 2025
I attempted to port the documentation build to use Zensical which is effectively the next generation of
MkDocs. To do this I needed to eliminate use of themarkdown-includeplugin and replace it with usage of thepymdownx.snippetsextension. That is all working fine.Building with
Zensicalalmost worked. The one one limitation I ran into is that currently the mkdocstrings extension for Zensical does not support cross-references yet:mkdocstringssupport was added to Zensical first on 2025-12-03, so this is under very rapid development and I expect within a month or so support formkdocstringscross-references will be available. Once that is there, everything should "just work". The documentation builds fast and looks even better than it did with MkDocs and the Material Theme.tleonhardt commentedon Dec 22, 2025
I created an issue in the
Zensicalproject about support formkdocstringscross-reference support: zensical/zensical#237Once that is available, I will re-visit porting the documentation to
Zensical.tleonhardt commentedon Dec 29, 2025
I've started experimenting with migrating to
prompt-toolkitfromreadlineon the prompt-toolkit branch.Things are getting close to working in a very basic rudimentary state.
rl_utils.pyhas been deleted and all use ofreadlinehas been replaced with use ofprompt-toollkit. All tests have been updated and are passing. A new filept_utils.pywas added as well as a new unit test file with tests to completely cover the code in the new file.There are inevitably other things that need to be addressed related to asyncio functionality, signal handlers, and blocking popen calls. We need to do a lot of manual testing to make sure everything appears to work as intended
tleonhardt commentedon Jan 20, 2026
prompt-toolkitsupport is working and a PR is up to review for it: #1553The documentation has been migrated to
zensicalin a separate PR which is also ready: #1557tleonhardt commentedon Jan 21, 2026
Documentation has been ported to
Zensicaland is looking fine on ReadTheDocs (RTD) as well as locally. Differential build is much faster as is the live preview reloading in the browser.tleonhardt commentedon Feb 21, 2026
Removed the Transcript Testing feature set in PR #1583
tleonhardt commentedon Mar 3, 2026
The 4.0.0b1 beta release of
cmd2is now available on PyPI and Release Notes are on GitHub.neoniobium commentedon Mar 5, 2026
Thank you for the great work on the beta release. I migrated an application yesterday. It all went smoothly.
I have a few points you might want to consider:
When completing strings from suggestions that contain empty spaces, quotes are applied atomically. When tapping through those suggestions, the quotation is only closed when exactly one match remains. This is sometimes very useful, but not always. It would be quite useful to have some level of control over that behavior.
I found it surprising that the choice from
prompt-toolkitis not used forcmd2.Cmd.select. I find its selection method (selecting withTab,Up,Downetc. instead of or in addition to pressing numbers) more convenient.I do not need it myself; however, I think a password input option from prompt would be a nice addition for
cmd2.Cmd.read_input.12 remaining items
neoniobium commentedon Apr 19, 2026
Thanks again for the new beta and especially for the detailed changelog. Each migration to a new beta went smoothly and did not take longer than 20 minutes.
I have some feedback:
Example:
'"This is a completion item"(tap here) — completer → '"This is a completion item""This is a completion item"'
Instead of:
'"This is a completion item"(tap here) — completer → '"This is a completion item"'
cmd.poutput-like commands, only a fewrich.console.ConsoleOptionsare passed to an object's__rich_console__dunder method via the intent interface (makeup,highlight, etc. are not passed through). I’m currently passing options these options by using therich_print_kwargsparameter, which doesn’t seem intended for allConsoleOptionsfields since theTypedDictfor that only lists a subset (seeRichPrintKwargs), so the type checker complains about my workaround. Is there a reason for this?kmvanbrunt commentedon Apr 19, 2026
@neoniobium
Thanks, I'll look into that tab completion issue.
justify,emoji,markup, andhighlightare direct arguments to thepoutput-like commands.RichPrintKwargsonly contains infrequently usedrich.console.print()keyword arguments. I put them in their own class to keep the already-long argument list of our print functions from getting even longer.neoniobium commentedon Apr 19, 2026
I might have phrased myself poorly. My concern isn’t how the
richarguments are organized, but that the keyword arguments (e.g.,highlight,markup— the ones not inRichPrintKwargs) don’t work as I expect when controlling aRenderablethat implements__rich_console__.When I pass
{"highlight": True}inside the dictionary given torich_print_kwargs, theRenderablebehaves as expected. When I passhighlight=Truedirectly as a keyword argument, it behaves differently. Inside__rich_console__I don’t seeoptions.highlightbeing set accordingly, but I can access thehighlightvalue when it’s passed viarich_print_kwargs.I’m not sure if this is expected behavior or whether I’m intended to control Renderables with
poutputetc. this way.kmvanbrunt commentedon Apr 19, 2026
That's because of a workaround in
cmd2for a Rich bug. We are not passingemoji,markup, orhighlighttoconsole.print(). We are passing them directly to theConsoleconstructor. This is because of two issues withRich.ConsoleOptionsis missing anemojifield. Therefore,emojioverrides passed toconsole.print()are ignored.Table,Rule,Columns, andMeasure) fail to pass some or all ofemoji,markup, andhighlightsettings from theirConsoleOptionsback toconsole.render_str().I filed this bug:
Textualize/rich#4028
And created this PR to fix it:
Textualize/rich#4084
Since we aren't passing them
console.print(), they aren't considered overrides to the underlyingConsole'sbehavior. Thereforeconsole.print()isn't setting them in theConsoleOptionsclass it passes around.However, the
Renderablesshould still print the same.I can pass them to
console.print()if you really need to see them in theConsoleOptionsobject. But that's not really necessary since the underlyingConsoleobject is already configured properly andconsole.render_str()will use the correct value.kmvanbrunt commentedon Apr 20, 2026
@neoniobium The completion bug is fixed in #1641
kmvanbrunt commentedon Apr 23, 2026
@neoniobium Beta 5 changed
rich_print_kwargsfrom aTypedDictto aMapping[str, Any]. So you can pass anything you want without receiving type errors.neoniobium commentedon Apr 24, 2026
@kmvanbrunt Thank you very much. I have checked out the latest beta and can confirm that both issues are fixed.
tleonhardt commentedon May 15, 2026
We now think that the
4.0.0release is feature complete minus one experimental feature in development. The4.0.0rc1release candidate is now available on PyPI.We would appreciate any and all help testing the Release Candidate and would like to hear about any bugs or suspected bugs. Suggestions for improving the documentation would be great, and PRs to do it would be even better ;-)
Please see the CHANGELOG for info on what has changed since
3.xand reference our documentation on cmd2 Major Versions Upgrades for tips on migrating.The Release Notes in GitHub also give some great info on what has changed since the last Beta release.
tleonhardt commentedon May 15, 2026
@KelvinChung2000 Hey Kelvin, now that we are feature complete and put out a release candidate, the hectic pace of changes should slow down considerably. When you have time could you please merge or rebase the latest stuff in
mainto yourfeat/annotated-argparsebranch and create a PR to merge that branch intomain?I'd like for @kmvanbrunt and myself to start taking a much closer look at that so we can get it into the final
4.0.0release as an experimental feature.traylenator commentedon May 20, 2026
Some feedback 4.0.0rc1 is building and testing okay in fedora rawhide with py3.14 and 3.15 on side branch.
https://src.fedoraproject.org/rpms/python-cmd2/pull-request/12
tleonhardt commentedon May 20, 2026
@traylenator Thanks for letting us know! We do really appreciate the positive feedback when downstream folks let us know there are no issues.
tleonhardt commentedon May 20, 2026
@traylenator Can you please elaborate on this comment in the link you gave?
Did we someone now comply with idiomatic processes for release candidates?
traylenator commentedon May 20, 2026
Sorry for the confusion, nothing to worry about. Everything is (very) good yourside.
The Version in that RPM spec file in that MR is wrong but your 4.0.0rc1 is perfect.
I am meant to do
and not what I did in the .spec so that it upgrades cleanly.
This is massively off topic for this thread so feel free to delete or hide these comments.
Thanks for making a RC, super useful.
tleonhardt commentedon Jun 5, 2026
The 4.0.0 release is now available on PyPI, the release notes are here on GitHub, and there is a Discussion open for chatting out it.
Its been a long-time coming and this is a big release.
Thanks to everyone that helped along the way to make it a reality!