diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index bdd7a3e3..c290a81a 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -14,21 +14,21 @@ orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or -advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a +- Other conduct which could reasonably be considered inappropriate in a professional setting ## Our Responsibilities diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 87bdc2a1..c7a43672 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -47,7 +47,7 @@ The tables below list all prerequisites along with the minimum required version #### Prerequisites to run cmd2 applications | Prerequisite | Minimum Version | Purpose | -|----------------------------------------------------------|-----------------|----------------------------------------| +| -------------------------------------------------------- | --------------- | -------------------------------------- | | [python](https://www.python.org/downloads/) | `3.9` | Python programming language | | [pyperclip](https://github.com/asweigart/pyperclip) | `1.8.2` | Cross-platform clipboard functions | | [rich-argparse](https://pypi.org/project/rich-argparse/) | `1.6.0` | Rich help formatters for argparse | @@ -56,7 +56,7 @@ The tables below list all prerequisites along with the minimum required version #### Additional prerequisites to build and publish cmd2 | Prerequisite | Minimum Version | Purpose | -|----------------------------------------------------------|-----------------|-------------------------------------| +| -------------------------------------------------------- | --------------- | ----------------------------------- | | [build](https://pypi.org/project/build/) | `1.2.2` | Python build frontend | | [setuptools](https://pypi.org/project/setuptools/) | `72.1.0` | Python package management | | [setuptools-scm](https://github.com/pypa/setuptools-scm) | `8.0.4` | Manage your versions by scm tag s | @@ -484,17 +484,17 @@ how to do it. 4. The title (also called the subject) of your PR should be descriptive of your changes and succinctly indicate what is being fixed - - **Do not add the issue number in the PR title or commit message** + - **Do not add the issue number in the PR title or commit message** - - Examples: `Add test cases for Unicode support`; `Correct typo in overview documentation` + - Examples: `Add test cases for Unicode support`; `Correct typo in overview documentation` 5. In the body of your PR include a more detailed summary of the changes you made and why - - If the PR is meant to fix an existing bug/issue, then, at the end of - your PR's description, append the keyword `closes` and #xxxx (where xxxx - is the issue number). Example: `closes #1337`. This tells GitHub to - close the existing issue if the PR is merged. + - If the PR is meant to fix an existing bug/issue, then, at the end of + your PR's description, append the keyword `closes` and #xxxx (where xxxx + is the issue number). Example: `closes #1337`. This tells GitHub to + close the existing issue if the PR is merged. 6. Indicate what local testing you have done (e.g. what OS and version(s) of Python did you run the unit test suite with) @@ -635,7 +635,7 @@ mostly automated. The manual steps are all git operations. Here's the checklist: 1. Make sure latest year in `LICENSE` matches current year 1. Make sure `CHANGELOG.md` describes the version and has the correct release date 1. Add a git tag representing the version number using `invoke tag x.y.z` - - Where x, y, and z are all small non-negative integers + - Where x, y, and z are all small non-negative integers 1. (Optional) Run `invoke pypi-test` to clean, build, and upload a new release to [Test PyPi](https://test.pypi.org) 1. Run `invoke pypi` to clean, build, and upload a new release to [PyPi](https://pypi.org/) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index ca4630c8..696b5d7b 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,11 +1,11 @@ version: 2 updates: -- package-ecosystem: "github-actions" - directory: "/" - schedule: + - package-ecosystem: "github-actions" + directory: "/" + schedule: interval: "weekly" -- package-ecosystem: "pip" - directory: "/" - schedule: + - package-ecosystem: "pip" + directory: "/" + schedule: interval: "weekly" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d27e3fcf..9f81a7a0 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -2,15 +2,15 @@ # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions name: "build" -on: [ push, pull_request ] +on: [push, pull_request] jobs: build: strategy: fail-fast: false matrix: - os: [ ubuntu-latest, macos-latest, windows-latest ] - python-version: [ "3.9", "3.10", "3.11", "3.12", "3.13" ] + os: [ubuntu-latest, macos-latest, windows-latest] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 # https://github.com/actions/checkout diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index edc40ddb..3f7be389 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -7,7 +7,7 @@ on: # The branches below must be a subset of the branches above branches: [master] schedule: - - cron: '0 6 * * 4' + - cron: "0 6 * * 4" permissions: contents: read @@ -15,9 +15,9 @@ permissions: jobs: analyze: permissions: - actions: read # for github/codeql-action/init to get workflow details - contents: read # for actions/checkout to fetch code - security-events: write # for github/codeql-action/autobuild to send a status report + actions: read # for github/codeql-action/init to get workflow details + contents: read # for actions/checkout to fetch code + security-events: write # for github/codeql-action/autobuild to send a status report name: Analyze runs-on: ubuntu-latest @@ -26,48 +26,48 @@ jobs: matrix: # Override automatic language detection by changing the below list # Supported options are ['csharp', 'cpp', 'go', 'java', 'javascript', 'python'] - language: ['python'] + language: ["python"] # Learn more... # https://docs.github.com/en/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#overriding-automatic-language-detection steps: - - name: Checkout repository - uses: actions/checkout@v4 - with: - # We must fetch at least the immediate parents so that if this is - # a pull request then we can checkout the head. - fetch-depth: 2 + - name: Checkout repository + uses: actions/checkout@v4 + with: + # We must fetch at least the immediate parents so that if this is + # a pull request then we can checkout the head. + fetch-depth: 2 - # If this run was triggered by a pull request event, then checkout - # the head of the pull request instead of the merge commit. - - run: git checkout HEAD^2 - if: ${{ github.event_name == 'pull_request' }} + # If this run was triggered by a pull request event, then checkout + # the head of the pull request instead of the merge commit. + - run: git checkout HEAD^2 + if: ${{ github.event_name == 'pull_request' }} - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - # queries: ./path/to/local/query, your-org/your-repo/queries@main + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main - # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). - # If this step fails, then you should remove it and run the build manually (see below) - - name: Autobuild - uses: github/codeql-action/autobuild@v3 + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v3 - # ℹ️ Command-line programs to run using the OS shell. - # 📚 https://git.io/JvXDl + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl - # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines - # and modify them (or add more) to build your code if your project - # uses a compiled language + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language - #- run: | - # make bootstrap - # make release + #- run: | + # make bootstrap + # make release - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/format.yml b/.github/workflows/format.yml index bbef3430..64923bb0 100644 --- a/.github/workflows/format.yml +++ b/.github/workflows/format.yml @@ -2,7 +2,7 @@ # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions name: Format -on: [ push, pull_request ] +on: [push, pull_request] permissions: contents: read @@ -11,7 +11,7 @@ jobs: format: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 # https://github.com/actions/checkout + - uses: actions/checkout@v4 # https://github.com/actions/checkout with: # Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. # Set fetch-depth: 0 to fetch all history for all branches and tags. diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 50913bcf..da02fcba 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,7 +2,7 @@ # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions name: Lint -on: [ push, pull_request ] +on: [push, pull_request] permissions: contents: read @@ -11,7 +11,7 @@ jobs: lint: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 # https://github.com/actions/checkout + - uses: actions/checkout@v4 # https://github.com/actions/checkout with: # Only a single commit is fetched by default, for the ref/SHA that triggered the workflow. # Set fetch-depth: 0 to fetch all history for all branches and tags. diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 99fa843d..e1a8c5f9 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -2,7 +2,7 @@ # https://docs.github.com/en/actions/reference/workflow-syntax-for-github-actions name: MyPy -on: [ push, pull_request ] +on: [push, pull_request] permissions: contents: read diff --git a/.gitignore b/.gitignore index 12886f83..6210f096 100644 --- a/.gitignore +++ b/.gitignore @@ -50,3 +50,8 @@ Pipfile.lock # uv uv.lock + +# Node/npm used for installing Prettier locally to override the outdated version that is bundled with the VSCode extension +node_modules/ +package-lock.json +package.json \ No newline at end of file diff --git a/.prettierrc b/.prettierrc index ae0bfe95..d903366c 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,10 +1,10 @@ { - "overrides": [ - { - "files": "*.md", - "options": { - "tabWidth": 4 - } + "overrides": [ + { + "files": "*.md", + "options": { + "tabWidth": 4 } - ] - } \ No newline at end of file + } + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa5dd4e..efa9dcfc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,1353 +1,1431 @@ ## 3.0.0 (TBD) -* Breaking Changes - * `cmd2` 3.x supports Python 3.9+ (removed support for Python 3.8) - * Removed macros -* Enhancements - * Simplified the process to set a custom parser for `cmd2's` built-in commands. - See [custom_parser.py](https://github.com/python-cmd2/cmd2/blob/master/examples/custom_parser.py) - example for more details. - * Integrated `rich-argparse` with `Cmd2HelpFormatter`. - * Added `RawDescriptionCmd2HelpFormatter`, `RawTextCmd2HelpFormatter`, `ArgumentDefaultsCmd2HelpFormatter`, - and `MetavarTypeCmd2HelpFormatter` and they all use `rich-argparse`. + +- Breaking Changes + - `cmd2` 3.x supports Python 3.9+ (removed support for Python 3.8) + - Removed macros +- Enhancements + - Simplified the process to set a custom parser for `cmd2's` built-in commands. + See [custom_parser.py](https://github.com/python-cmd2/cmd2/blob/master/examples/custom_parser.py) + example for more details. + - Integrated `rich-argparse` with `Cmd2HelpFormatter`. + - Added `RawDescriptionCmd2HelpFormatter`, `RawTextCmd2HelpFormatter`, `ArgumentDefaultsCmd2HelpFormatter`, + and `MetavarTypeCmd2HelpFormatter` and they all use `rich-argparse`. + +## 2.5.9 (TBD) + +- Bug Fixes + - Fixed 'index out of range' error when passing no arguments to an argparse-based command function. ## 2.5.8 (December 17, 2024) -* Bug Fixes - * Rolled back undocumented changes to printing functions introduced in 2.5.0. + +- Bug Fixes + - Rolled back undocumented changes to printing functions introduced in 2.5.0. ## 2.5.7 (November 22, 2024) -* Bug Fixes - * Fixed issue where argument parsers for overridden commands were not being created. - * Fixed issue where `Cmd.ppaged()` was not writing to the passed in destination. + +- Bug Fixes + - Fixed issue where argument parsers for overridden commands were not being created. + - Fixed issue where `Cmd.ppaged()` was not writing to the passed in destination. ## 2.5.6 (November 14, 2024) -* Bug Fixes - * Fixed type hint for `with_default_category` decorator which caused type checkers to mistype - a subclass of `CommandSet` as a plain `CommandSet`. + +- Bug Fixes + - Fixed type hint for `with_default_category` decorator which caused type checkers to mistype + a subclass of `CommandSet` as a plain `CommandSet`. ## 2.5.5 (November 13, 2024) -* Bug Fixes - * Fixed type hints for passing a class method to `with_argparser` and `as_subcommand_to`. - * Fixed issue where `set` command was not always printing a settable's current value. + +- Bug Fixes + - Fixed type hints for passing a class method to `with_argparser` and `as_subcommand_to`. + - Fixed issue where `set` command was not always printing a settable's current value. ## 2.5.4 (November 6, 2024) -* Bug Fixes - * Fixed `ZeroDivisionError` in `async_alert()` when `shutil.get_terminal_size().columns` is 0. + +- Bug Fixes + - Fixed `ZeroDivisionError` in `async_alert()` when `shutil.get_terminal_size().columns` is 0. ## 2.5.3 (November 5, 2024) -* Enhancements - * Changed `CommandSet._cmd` to a read-only property which never returns `None` because it - is meant to be called after the `CommandSet` is registered. This addresses type checker - errors that occurred if `CommandSet._cmd` wasn't cast or checked if `None` before use. + +- Enhancements + - Changed `CommandSet._cmd` to a read-only property which never returns `None` because it + is meant to be called after the `CommandSet` is registered. This addresses type checker + errors that occurred if `CommandSet._cmd` wasn't cast or checked if `None` before use. ## 2.5.2 (November 3, 2024) -* Bug Fixes - * Fixed default `pytest` execution when not using cmd2's custom `invoke` command via `inv pytest` + +- Bug Fixes + - Fixed default `pytest` execution when not using cmd2's custom `invoke` command via `inv pytest` ## 2.5.1 (November 2, 2024) -* Bug Fixes - * Fixed readline bug when using `ipy` command with `gnureadline` and Python 3.13 + +- Bug Fixes + - Fixed readline bug when using `ipy` command with `gnureadline` and Python 3.13 ## 2.5.0 (October 23, 2024) -* Breaking Change - * `cmd2` 2.5 supports Python 3.8+ (removed support for Python 3.6 and 3.7) -* Bug Fixes - * Fixed issue where persistent history file was not saved upon SIGHUP and SIGTERM signals. - * Multiline commands are no longer fragmented in up-arrow history. - * Fixed bug where `async_alert()` overwrites readline's incremental and non-incremental search prompts. - * This fix introduces behavior where an updated prompt won't display after an aborted search - until a user presses Enter. See [async_printing.py](https://github.com/python-cmd2/cmd2/blob/master/examples/async_printing.py) - example for how to handle this case using `Cmd.need_prompt_refresh()` and `Cmd.async_refresh_prompt()`. -* Enhancements - * Removed dependency on `attrs` and replaced with [dataclasses](https://docs.python.org/3/library/dataclasses.html) - * add `allow_clipboard` initialization parameter and attribute to disable ability to - add output to the operating system clipboard - * Updated unit tests to be Python 3.13 compliant. - * Fall back to bz2 compression of history file when lzma is not installed. - * Added settable called `scripts_add_to_history` which determines whether scripts and pyscripts - add commands to history. -* Deletions (potentially breaking changes) - * Removed `apply_style` from `Cmd.pwarning()`. + +- Breaking Change + - `cmd2` 2.5 supports Python 3.8+ (removed support for Python 3.6 and 3.7) +- Bug Fixes + - Fixed issue where persistent history file was not saved upon SIGHUP and SIGTERM signals. + - Multiline commands are no longer fragmented in up-arrow history. + - Fixed bug where `async_alert()` overwrites readline's incremental and non-incremental search prompts. + - This fix introduces behavior where an updated prompt won't display after an aborted search + until a user presses Enter. See [async_printing.py](https://github.com/python-cmd2/cmd2/blob/master/examples/async_printing.py) + example for how to handle this case using `Cmd.need_prompt_refresh()` and `Cmd.async_refresh_prompt()`. +- Enhancements + - Removed dependency on `attrs` and replaced with [dataclasses](https://docs.python.org/3/library/dataclasses.html) + - add `allow_clipboard` initialization parameter and attribute to disable ability to + add output to the operating system clipboard + - Updated unit tests to be Python 3.13 compliant. + - Fall back to bz2 compression of history file when lzma is not installed. + - Added settable called `scripts_add_to_history` which determines whether scripts and pyscripts + add commands to history. +- Deletions (potentially breaking changes) + - Removed `apply_style` from `Cmd.pwarning()`. ## 2.4.3 (January 27, 2023) -* Bug Fixes - * Fixed ValueError caused when passing `Cmd.columnize()` strings wider than `display_width`. -* Enhancements - * Renamed `utils.str_to_bool()` -> `utils.to_bool()`. - * Enhanced `utils.to_bool()` so that it accepts and converts `bool`, `int`, and `float` in addition to `str`. + +- Bug Fixes + - Fixed ValueError caused when passing `Cmd.columnize()` strings wider than `display_width`. +- Enhancements + - Renamed `utils.str_to_bool()` -> `utils.to_bool()`. + - Enhanced `utils.to_bool()` so that it accepts and converts `bool`, `int`, and `float` in addition to `str`. ## 2.4.2 (July 13, 2022) -* Enhancements - * Updated argparse decorator to remove annotations when the docstring is used for a command's help text. - * Updated unit test to be Python 3.11 compliant. + +- Enhancements + - Updated argparse decorator to remove annotations when the docstring is used for a command's help text. + - Updated unit test to be Python 3.11 compliant. ## 2.4.1 (April 13, 2022) -* Bug Fixes - * Fixed value for `ansi.Bg.YELLOW`. - * Fixed unit tests for `ansi.allow_style`. -* Enhancements - * `async_alert()` raises a `RuntimeError` if called from the main thread. + +- Bug Fixes + - Fixed value for `ansi.Bg.YELLOW`. + - Fixed unit tests for `ansi.allow_style`. +- Enhancements + - `async_alert()` raises a `RuntimeError` if called from the main thread. ## 2.4.0 (February 22, 2022) -* Bug Fixes - * Fixed issue in `ansi.async_alert_str()` which would raise `IndexError` if prompt was blank. - * Fixed issue where tab completion was quoting argparse flags in some cases. -* Enhancements - * Added broader exception handling when enabling clipboard functionality via `pyperclip`. - * Added `PassThroughException` to `__init__.py` imports. - * cmd2 now uses pyreadline3 when running any version of Python on Windows - * Improved memory usage in certain use cases of tables (e.g. nested colored tables) -* Deletions (potentially breaking changes) - * Deleted `cmd2.fg` and `cmd2.bg` which were deprecated in 2.3.0. Use `cmd2.Fg` and `cmd2.Bg` instead. + +- Bug Fixes + - Fixed issue in `ansi.async_alert_str()` which would raise `IndexError` if prompt was blank. + - Fixed issue where tab completion was quoting argparse flags in some cases. +- Enhancements + - Added broader exception handling when enabling clipboard functionality via `pyperclip`. + - Added `PassThroughException` to `__init__.py` imports. + - cmd2 now uses pyreadline3 when running any version of Python on Windows + - Improved memory usage in certain use cases of tables (e.g. nested colored tables) +- Deletions (potentially breaking changes) + - Deleted `cmd2.fg` and `cmd2.bg` which were deprecated in 2.3.0. Use `cmd2.Fg` and `cmd2.Bg` instead. ## 2.3.3 (November 29, 2021) -* Enhancements - * Added clearer exception handling to `BorderedTable` and `SimpleTable`. + +- Enhancements + - Added clearer exception handling to `BorderedTable` and `SimpleTable`. ## 2.3.2 (November 22, 2021) -* Bug Fixes - * Fixed issue where a `ns_provider` could be passed `None` instead of its correct `cmd2.Cmd` or `CommandSet` value. + +- Bug Fixes + - Fixed issue where a `ns_provider` could be passed `None` instead of its correct `cmd2.Cmd` or `CommandSet` value. ## 2.3.1 (November 18, 2021) -* Bug Fixes - * Fixed issue introduced in 2.3.0 with `AlternatingTable`, `BorderedTable`, and `SimpleTable` that caused - header alignment settings to be overridden by data alignment settings. -* Enhancements - * `CompletionItems` now saves the original object from which it creates a string. - * Using `CompletionItems` as argparse choices is fully supported. `cmd2` patched `argparse` to compare input to - the original value instead of the `CompletionItems` instance. - * `ArgparseCompleter` now does the following if a list of `CompletionItems` was created with numerical types: - * Sorts completion hints numerically - * Right-aligns the left-most column in completion hint table + +- Bug Fixes + - Fixed issue introduced in 2.3.0 with `AlternatingTable`, `BorderedTable`, and `SimpleTable` that caused + header alignment settings to be overridden by data alignment settings. +- Enhancements + - `CompletionItems` now saves the original object from which it creates a string. + - Using `CompletionItems` as argparse choices is fully supported. `cmd2` patched `argparse` to compare input to + the original value instead of the `CompletionItems` instance. + - `ArgparseCompleter` now does the following if a list of `CompletionItems` was created with numerical types: + - Sorts completion hints numerically + - Right-aligns the left-most column in completion hint table ## 2.3.0 (November 11, 2021) -* Bug Fixes - * Fixed `AttributeError` in `rl_get_prompt()` when prompt is `None`. - * Fixed bug where using choices on a Settable didn't verify that a valid choice had been entered. - * Fixed bug introduced in cmd2 2.0.0 in which `select()` converts return values to strings. It should never - have converted return values. -* Enhancements - * Added settings to Column class which prevent a table from overriding existing styles in header - and/or data text. This allows for things like nesting an AlternatingTable in another AlternatingTable. - * AlternatingTable no longer automatically applies background color to borders. This was done to improve - appearance since the background color extended beyond the borders of the table. - * Added ability to colorize all aspects of `AlternatingTable`, `BorderedTable`, and `SimpleTable`. - * Added support for 8-bit/256-colors with the `cmd2.EightBitFg` and `cmd2.EightBitBg` classes. - * Added support for 24-bit/RGB colors with the `cmd2.RgbFg` and `cmd2.RgbBg` classes. - * Removed dependency on colorama. - * Changed type of `ansi.allow_style` from a string to an `ansi.AllowStyle` Enum class. -* Deprecations - * Deprecated `cmd2.fg`. Use `cmd2.Fg` instead. - * Deprecated `cmd2.bg`. Use `cmd2.Bg` instead. -* Breaking Changes - * To support the color upgrade, all cmd2 colors now inherit from either `ansi.FgColor` or `ansi.BgColor`. - Therefore, `ansi.style()` no longer accepts colors as strings. + +- Bug Fixes + - Fixed `AttributeError` in `rl_get_prompt()` when prompt is `None`. + - Fixed bug where using choices on a Settable didn't verify that a valid choice had been entered. + - Fixed bug introduced in cmd2 2.0.0 in which `select()` converts return values to strings. It should never + have converted return values. +- Enhancements + - Added settings to Column class which prevent a table from overriding existing styles in header + and/or data text. This allows for things like nesting an AlternatingTable in another AlternatingTable. + - AlternatingTable no longer automatically applies background color to borders. This was done to improve + appearance since the background color extended beyond the borders of the table. + - Added ability to colorize all aspects of `AlternatingTable`, `BorderedTable`, and `SimpleTable`. + - Added support for 8-bit/256-colors with the `cmd2.EightBitFg` and `cmd2.EightBitBg` classes. + - Added support for 24-bit/RGB colors with the `cmd2.RgbFg` and `cmd2.RgbBg` classes. + - Removed dependency on colorama. + - Changed type of `ansi.allow_style` from a string to an `ansi.AllowStyle` Enum class. +- Deprecations + - Deprecated `cmd2.fg`. Use `cmd2.Fg` instead. + - Deprecated `cmd2.bg`. Use `cmd2.Bg` instead. +- Breaking Changes + - To support the color upgrade, all cmd2 colors now inherit from either `ansi.FgColor` or `ansi.BgColor`. + Therefore, `ansi.style()` no longer accepts colors as strings. ## 2.2.0 (September 14, 2021) -* Bug Fixes - * Fixed extra space appended to each alias by "alias list" command -* Enhancements - * New function `set_default_ap_completer_type()` allows developer to extend and modify the - behavior of `ArgparseCompleter`. - * Added `ArgumentParser.get_ap_completer_type()` and `ArgumentParser.set_ap_completer_type()`. These - methods allow developers to enable custom tab completion behavior for a given parser by using a custom - `ArgparseCompleter`-based class. - * Added `ap_completer_type` keyword arg to `Cmd2ArgumentParser.__init__()` which saves a call - to `set_ap_completer_type()`. This keyword will also work with `add_parser()` when creating subcommands - if the base command's parser is a `Cmd2ArgumentParser`. - * New function `register_argparse_argument_parameter()` allows developers to specify custom - parameters to be passed to the argparse parser's `add_argument()` method. These parameters will - become accessible in the resulting argparse Action object when modifying `ArgparseCompleter` behavior. - * Using `SimpleTable` in the output for the following commands to improve appearance. - * help - * set (command and tab completion of Settables) - * alias tab completion - * macro tab completion - * Tab completion of `CompletionItems` now includes divider row comprised of `Cmd.ruler` character. - * Removed `--verbose` flag from set command since descriptions always show now. - * All cmd2 built-in commands now populate `self.last_result`. - * Argparse tab completer will complete remaining flag names if there are no more positionals to complete. - * Updated `async_alert()` to account for `self.prompt` not matching Readline's current prompt. -* Deletions (potentially breaking changes) - * Deleted `set_choices_provider()` and `set_completer()` which were deprecated in 2.1.2 -* Breaking Changes - * Renamed `set_default_argument_parser()` to `set_default_argument_parser_type()` + +- Bug Fixes + - Fixed extra space appended to each alias by "alias list" command +- Enhancements + - New function `set_default_ap_completer_type()` allows developer to extend and modify the + behavior of `ArgparseCompleter`. + - Added `ArgumentParser.get_ap_completer_type()` and `ArgumentParser.set_ap_completer_type()`. These + methods allow developers to enable custom tab completion behavior for a given parser by using a custom + `ArgparseCompleter`-based class. + - Added `ap_completer_type` keyword arg to `Cmd2ArgumentParser.__init__()` which saves a call + to `set_ap_completer_type()`. This keyword will also work with `add_parser()` when creating subcommands + if the base command's parser is a `Cmd2ArgumentParser`. + - New function `register_argparse_argument_parameter()` allows developers to specify custom + parameters to be passed to the argparse parser's `add_argument()` method. These parameters will + become accessible in the resulting argparse Action object when modifying `ArgparseCompleter` behavior. + - Using `SimpleTable` in the output for the following commands to improve appearance. + - help + - set (command and tab completion of Settables) + - alias tab completion + - macro tab completion + - Tab completion of `CompletionItems` now includes divider row comprised of `Cmd.ruler` character. + - Removed `--verbose` flag from set command since descriptions always show now. + - All cmd2 built-in commands now populate `self.last_result`. + - Argparse tab completer will complete remaining flag names if there are no more positionals to complete. + - Updated `async_alert()` to account for `self.prompt` not matching Readline's current prompt. +- Deletions (potentially breaking changes) + - Deleted `set_choices_provider()` and `set_completer()` which were deprecated in 2.1.2 +- Breaking Changes + - Renamed `set_default_argument_parser()` to `set_default_argument_parser_type()` ## 2.1.2 (July 5, 2021) -* Enhancements - * Added the following accessor methods for cmd2-specific attributes to the `argparse.Action` class - * `get_choices_callable()` - * `set_choices_provider()` - * `set_completer()` - * `get_descriptive_header()` - * `set_descriptive_header()` - * `get_nargs_range()` - * `set_nargs_range()` - * `get_suppress_tab_hint()` - * `set_suppress_tab_hint()` -* Deprecations - * Now that `set_choices_provider()` and `set_completer()` have been added as methods to the + +- Enhancements + - Added the following accessor methods for cmd2-specific attributes to the `argparse.Action` class + - `get_choices_callable()` + - `set_choices_provider()` + - `set_completer()` + - `get_descriptive_header()` + - `set_descriptive_header()` + - `get_nargs_range()` + - `set_nargs_range()` + - `get_suppress_tab_hint()` + - `set_suppress_tab_hint()` +- Deprecations + - Now that `set_choices_provider()` and `set_completer()` have been added as methods to the `argparse.Action` class, the standalone functions of the same name will be removed in version 2.2.0. To update to the new convention, do the following: - * Change `set_choices_provider(action, provider)` to `action.set_choices_provider(provider)` - * Change `set_completer(action, completer)` to `action.set_completer(completer)` + - Change `set_choices_provider(action, provider)` to `action.set_choices_provider(provider)` + - Change `set_completer(action, completer)` to `action.set_completer(completer)` ## 2.1.1 (June 17, 2021) -* Bug Fixes - * Fixed handling of argparse's default options group name which was changed in Python 3.10 -* Enhancements - * Restored `plugins` and `tests_isolated` directories to tarball published to PyPI for `cmd2` release + +- Bug Fixes + - Fixed handling of argparse's default options group name which was changed in Python 3.10 +- Enhancements + - Restored `plugins` and `tests_isolated` directories to tarball published to PyPI for `cmd2` release ## 2.1.0 (June 14, 2021) -* Enhancements - * Converted persistent history files from pickle to compressed JSON + +- Enhancements + - Converted persistent history files from pickle to compressed JSON ## 2.0.1 (June 7, 2021) -* Bug Fixes - * Exclude `plugins` and `tests_isolated` directories from tarball published to PyPI for `cmd2` release + +- Bug Fixes + - Exclude `plugins` and `tests_isolated` directories from tarball published to PyPI for `cmd2` release ## 2.0.0 (June 6, 2021) -* Bug Fixes - * Fixed issue where history indexes could get repeated - * Fixed issue where TableCreator was tossing blank last line - * Corrected help text for alias command -* Breaking Changes - * `cmd2` 2.0 supports Python 3.6+ (removed support for Python 3.5) - * Argparse Completion / Settables - * Replaced `choices_function` / `choices_method` with `choices_provider`. - * Replaced `completer_function` / `completer_method` with `completer`. - * ArgparseCompleter now always passes `cmd2.Cmd` or `CommandSet` instance as the first positional - argument to choices_provider and completer functions. - * Moved `basic_complete` from utils into `cmd2.Cmd` class. - * Moved `CompletionError` to exceptions.py - * ``Namespace.__statement__`` has been removed. Use `Namespace.cmd2_statement.get()` instead. - * Removed `--silent` flag from `alias/macro create` since startup scripts can be run silently. - * Removed `--with_silent` flag from `alias/macro list` since startup scripts can be run silently. - * Removed `with_argparser_and_unknown_args` since it was deprecated in 1.3.0. - * Renamed `silent_startup_script` to `silence_startup_script` for clarity. - * Replaced `cmd2.Cmd.completion_header` with `cmd2.Cmd.formatted_completions`. See Enhancements + +- Bug Fixes + - Fixed issue where history indexes could get repeated + - Fixed issue where TableCreator was tossing blank last line + - Corrected help text for alias command +- Breaking Changes + - `cmd2` 2.0 supports Python 3.6+ (removed support for Python 3.5) + - Argparse Completion / Settables + - Replaced `choices_function` / `choices_method` with `choices_provider`. + - Replaced `completer_function` / `completer_method` with `completer`. + - ArgparseCompleter now always passes `cmd2.Cmd` or `CommandSet` instance as the first positional + argument to choices_provider and completer functions. + - Moved `basic_complete` from utils into `cmd2.Cmd` class. + - Moved `CompletionError` to exceptions.py + - `Namespace.__statement__` has been removed. Use `Namespace.cmd2_statement.get()` instead. + - Removed `--silent` flag from `alias/macro create` since startup scripts can be run silently. + - Removed `--with_silent` flag from `alias/macro list` since startup scripts can be run silently. + - Removed `with_argparser_and_unknown_args` since it was deprecated in 1.3.0. + - Renamed `silent_startup_script` to `silence_startup_script` for clarity. + - Replaced `cmd2.Cmd.completion_header` with `cmd2.Cmd.formatted_completions`. See Enhancements for description of this new class member. - * Settables now have new initialization parameters. It is now a required parameter to supply the reference to the + - Settables now have new initialization parameters. It is now a required parameter to supply the reference to the object that holds the settable attribute. `cmd2.Cmd.settables` is no longer a public dict attribute - it is now a property that aggregates all Settables across all registered CommandSets. - * Failed transcript testing now sets self.exit_code to 1 instead of -1. - * Renamed `use_ipython` keyword parameter of `cmd2.Cmd.__init__()` to `include_ipy`. - * `py` command is only enabled if `include_py` parameter is `True`. See Enhancements for a description + - Failed transcript testing now sets self.exit_code to 1 instead of -1. + - Renamed `use_ipython` keyword parameter of `cmd2.Cmd.__init__()` to `include_ipy`. + - `py` command is only enabled if `include_py` parameter is `True`. See Enhancements for a description of this parameter. - * Removed ability to run Python commands from the command line with `py`. Now `py` takes no arguments + - Removed ability to run Python commands from the command line with `py`. Now `py` takes no arguments and just opens an interactive Python shell. - * Changed default behavior of `runcmds_plus_hooks()` to not stop when Ctrl-C is pressed and instead + - Changed default behavior of `runcmds_plus_hooks()` to not stop when Ctrl-C is pressed and instead run the next command in its list. - * Removed `cmd2.Cmd.quit_on_sigint` flag, which when `True`, quit the application when Ctrl-C was pressed at the prompt. - * The history bug fix resulted in structure changes to the classes in `cmd2.history`. Therefore, persistent history + - Removed `cmd2.Cmd.quit_on_sigint` flag, which when `True`, quit the application when Ctrl-C was pressed at the prompt. + - The history bug fix resulted in structure changes to the classes in `cmd2.history`. Therefore, persistent history files created with versions older than 2.0.0 are not compatible. -* Enhancements - * Added support for custom tab completion and up-arrow input history to `cmd2.Cmd2.read_input`. +- Enhancements + - Added support for custom tab completion and up-arrow input history to `cmd2.Cmd2.read_input`. See [read_input.py](https://github.com/python-cmd2/cmd2/blob/master/examples/read_input.py) for an example. - * Added `cmd2.exceptions.PassThroughException` to raise unhandled command exceptions instead of printing them. - * Added support for ANSI styles and newlines in tab completion results using `cmd2.Cmd.formatted_completions`. + - Added `cmd2.exceptions.PassThroughException` to raise unhandled command exceptions instead of printing them. + - Added support for ANSI styles and newlines in tab completion results using `cmd2.Cmd.formatted_completions`. `cmd2` provides this capability automatically if you return argparse completion matches as `CompletionItems`. - * Settables enhancements: - * Settables may be optionally scoped to a CommandSet. Settables added to CommandSets will appear when a + - Settables enhancements: + - Settables may be optionally scoped to a CommandSet. Settables added to CommandSets will appear when a CommandSet is registered and disappear when a CommandSet is unregistered. Optionally, scoped Settables may have a prepended prefix. - * Settables now allow changes to be applied to any arbitrary object attribute. It no longer needs to match an + - Settables now allow changes to be applied to any arbitrary object attribute. It no longer needs to match an attribute added to the cmd2 instance itself. - * Raising ``SystemExit`` or calling ``sys.exit()`` in a command or hook function will set ``self.exit_code`` + - Raising `SystemExit` or calling `sys.exit()` in a command or hook function will set `self.exit_code` to the exit code used in those calls. It will also result in the command loop stopping. - * ipy command now includes all of `self.py_locals` in the IPython environment - * Added `include_py` keyword parameter to `cmd2.Cmd.__init__()`. If `False`, then the `py` command will + - ipy command now includes all of `self.py_locals` in the IPython environment + - Added `include_py` keyword parameter to `cmd2.Cmd.__init__()`. If `False`, then the `py` command will not be available. Defaults to `False`. `run_pyscript` is not affected by this parameter. - * Made the amount of space between columns in a SimpleTable configurable - * On POSIX systems, shell commands and processes being piped to are now run in the user's preferred shell + - Made the amount of space between columns in a SimpleTable configurable + - On POSIX systems, shell commands and processes being piped to are now run in the user's preferred shell instead of /bin/sh. The preferred shell is obtained by reading the SHELL environment variable. If that doesn't exist or is empty, then /bin/sh is used. - * Changed `cmd2.Cmd._run_editor()` to the public method `cmd2.Cmd.run_editor()` + - Changed `cmd2.Cmd._run_editor()` to the public method `cmd2.Cmd.run_editor()` ## 1.5.0 (January 31, 2021) -* Bug Fixes - * Fixed bug where setting `always_show_hint=True` did not show a hint when completing `Settables` - * Fixed bug in editor detection logic on Linux systems that do not have `which` - * Fixed bug in table creator where column headers with tabs would result in an incorrect width calculation - * Fixed `FileNotFoundError` which occurred when running `history --clear` and no history file existed. -* Enhancements - * Added `silent_startup_script` option to `cmd2.Cmd.__init__()`. If `True`, then the startup script's + +- Bug Fixes + - Fixed bug where setting `always_show_hint=True` did not show a hint when completing `Settables` + - Fixed bug in editor detection logic on Linux systems that do not have `which` + - Fixed bug in table creator where column headers with tabs would result in an incorrect width calculation + - Fixed `FileNotFoundError` which occurred when running `history --clear` and no history file existed. +- Enhancements + - Added `silent_startup_script` option to `cmd2.Cmd.__init__()`. If `True`, then the startup script's output will be suppressed. Anything written to stderr will still display. - * cmd2 now uses pyreadline3 when running Python 3.8 or greater on Windows -* Notes - * This is the last release planned to support Python 3.5 + - cmd2 now uses pyreadline3 when running Python 3.8 or greater on Windows +- Notes + - This is the last release planned to support Python 3.5 ## 1.4.0 (November 11, 2020) -* Bug Fixes - * Fixed tab completion crash on Windows -* Enhancements - * Changed how multiline doc string help is formatted to match style of other help messages + +- Bug Fixes + - Fixed tab completion crash on Windows +- Enhancements + - Changed how multiline doc string help is formatted to match style of other help messages ## 1.3.11 (October 1, 2020) -* Bug Fixes - * Fixed issue where quoted redirectors and terminators in aliases and macros were not being - restored when read from a startup script. - * Fixed issue where instantiating more than one cmd2-based class which uses the `@as_subcommand_to` - decorator resulted in duplicated help text in the base command the subcommands belong to. + +- Bug Fixes + - Fixed issue where quoted redirectors and terminators in aliases and macros were not being + restored when read from a startup script. + - Fixed issue where instantiating more than one cmd2-based class which uses the `@as_subcommand_to` + decorator resulted in duplicated help text in the base command the subcommands belong to. ## 1.3.10 (September 17, 2020) -* Enhancements - * Added user-settable option called `always_show_hint`. If True, then tab completion hints will always - display even when tab completion suggestions print. Arguments whose help or hint text is suppressed will - not display hints even when this setting is True. - * argparse tab completion now groups flag names which run the same action. Optional flags are wrapped - in brackets like it is done in argparse usage text. - * default category decorators are now heritable by default and will propagate the category down the - class hierarchy until overridden. There's a new optional flag to set heritable to false. - * Added `--silent` flag to `alias/macro create`. If used, then no confirmation message will be printed - when aliases and macros are created or overwritten. - * Added `--with_silent` flag to `alias/macro list`. Use this option when saving to a startup script - that should silently create aliases and macros. -* Bug Fixes - * Fixed issue where flag names weren't always sorted correctly in argparse tab completion + +- Enhancements + - Added user-settable option called `always_show_hint`. If True, then tab completion hints will always + display even when tab completion suggestions print. Arguments whose help or hint text is suppressed will + not display hints even when this setting is True. + - argparse tab completion now groups flag names which run the same action. Optional flags are wrapped + in brackets like it is done in argparse usage text. + - default category decorators are now heritable by default and will propagate the category down the + class hierarchy until overridden. There's a new optional flag to set heritable to false. + - Added `--silent` flag to `alias/macro create`. If used, then no confirmation message will be printed + when aliases and macros are created or overwritten. + - Added `--with_silent` flag to `alias/macro list`. Use this option when saving to a startup script + that should silently create aliases and macros. +- Bug Fixes + - Fixed issue where flag names weren't always sorted correctly in argparse tab completion ## 1.3.9 (September 03, 2020) -* Breaking Changes - * `CommandSet.on_unregister()` is now called as first step in unregistering a `CommandSet` and not - the last. `CommandSet.on_unregistered()` is now the last step. -* Enhancements - * Added `CommandSet.on_registered()`. This is called by `cmd2.Cmd` after a `CommandSet` is registered - and all its commands have been added to the CLI. - * Added `CommandSet.on_unregistered()`. This is called by `cmd2.Cmd` after a `CommandSet` is unregistered - and all its commands have been removed from the CLI. + +- Breaking Changes + - `CommandSet.on_unregister()` is now called as first step in unregistering a `CommandSet` and not + the last. `CommandSet.on_unregistered()` is now the last step. +- Enhancements + - Added `CommandSet.on_registered()`. This is called by `cmd2.Cmd` after a `CommandSet` is registered + and all its commands have been added to the CLI. + - Added `CommandSet.on_unregistered()`. This is called by `cmd2.Cmd` after a `CommandSet` is unregistered + and all its commands have been removed from the CLI. ## 1.3.8 (August 28, 2020) -* Bug Fixes - * Fixed issue where subcommand added with `@as_subcommand_to` decorator did not display help - when called with `-h/--help`. -* Enhancements - * `add_help=False` no longer has to be passed to parsers used in `@as_subcommand_to` decorator. + +- Bug Fixes + - Fixed issue where subcommand added with `@as_subcommand_to` decorator did not display help + when called with `-h/--help`. +- Enhancements + - `add_help=False` no longer has to be passed to parsers used in `@as_subcommand_to` decorator. Only pass this if your subcommand should not have the `-h/--help` help option (as stated in argparse documentation). ## 1.3.7 (August 27, 2020) -* Bug Fixes - * Fixes an issue introduced in 1.3.0 with processing command strings containing terminator/separator + +- Bug Fixes + - Fixes an issue introduced in 1.3.0 with processing command strings containing terminator/separator character(s) that are manually passed to a command that uses argparse. ## 1.3.6 (August 27, 2020) -* Breaking changes - * The functions cmd2 adds to Namespaces (`get_statement()` and `get_handler()`) are now - `Cmd2AttributeWrapper` objects named `cmd2_statement` and `cmd2_handler`. This makes it - easy to filter out which attributes in an `argparse.Namespace` were added by `cmd2`. -* Deprecations - * ``Namespace.__statement__`` will be removed in `cmd2` 2.0.0. Use `Namespace.cmd2_statement.get()` - going forward. + +- Breaking changes + - The functions cmd2 adds to Namespaces (`get_statement()` and `get_handler()`) are now + `Cmd2AttributeWrapper` objects named `cmd2_statement` and `cmd2_handler`. This makes it + easy to filter out which attributes in an `argparse.Namespace` were added by `cmd2`. +- Deprecations + - `Namespace.__statement__` will be removed in `cmd2` 2.0.0. Use `Namespace.cmd2_statement.get()` + going forward. ## 1.3.5 (August 25, 2020) -* Bug Fixes - * Fixed `RecursionError` when printing an `argparse.Namespace` caused by custom attribute cmd2 was adding -* Enhancements - * Added `get_statement()` function to `argparse.Namespace` which returns `__statement__` attribute + +- Bug Fixes + - Fixed `RecursionError` when printing an `argparse.Namespace` caused by custom attribute cmd2 was adding +- Enhancements + - Added `get_statement()` function to `argparse.Namespace` which returns `__statement__` attribute ## 1.3.4 (August 20, 2020) -* Bug Fixes - * Fixed `AttributeError` when `CommandSet` that uses `as_subcommand_to` decorator is loaded during - `cmd2.Cmd.__init__()`. -* Enhancements - * Improved exception messages when using mock without `spec=True`. - See [testing](https://cmd2.readthedocs.io/en/latest/testing.html) documentation for more details on testing - cmd2-based applications with mock. + +- Bug Fixes + - Fixed `AttributeError` when `CommandSet` that uses `as_subcommand_to` decorator is loaded during + `cmd2.Cmd.__init__()`. +- Enhancements + - Improved exception messages when using mock without `spec=True`. + See [testing](https://cmd2.readthedocs.io/en/latest/testing.html) documentation for more details on testing + cmd2-based applications with mock. ## 1.3.3 (August 13, 2020) -* Breaking changes - * CommandSet command functions (do_, complete_, help_) will no longer have the cmd2 app + +- Breaking changes + - CommandSet command functions (do*, complete*, help\_) will no longer have the cmd2 app passed in as the first parameter after `self` since this is already a class member. - * Renamed `install_command_set()` and `uninstall_command_set()` to `register_command_set()` and + - Renamed `install_command_set()` and `uninstall_command_set()` to `register_command_set()` and `unregister_command_set()` for better name consistency. -* Bug Fixes - * Fixed help formatting bug in `Cmd2ArgumentParser` when `metavar` is a tuple - * Fixed tab completion bug when using `CompletionItem` on an argument whose `metavar` is a tuple - * Added explicit testing against python 3.5.2 for Ubuntu 16.04, and 3.5.3 for Debian 9 - * Added fallback definition of typing.Deque (taken from 3.5.4) - * Removed explicit type hints that fail due to a bug in 3.5.2 favoring comment-based hints instead - * When passing a ns_provider to an argparse command, will now attempt to resolve the correct +- Bug Fixes + - Fixed help formatting bug in `Cmd2ArgumentParser` when `metavar` is a tuple + - Fixed tab completion bug when using `CompletionItem` on an argument whose `metavar` is a tuple + - Added explicit testing against python 3.5.2 for Ubuntu 16.04, and 3.5.3 for Debian 9 + - Added fallback definition of typing.Deque (taken from 3.5.4) + - Removed explicit type hints that fail due to a bug in 3.5.2 favoring comment-based hints instead + - When passing a ns_provider to an argparse command, will now attempt to resolve the correct CommandSet instance for self. If not, it'll fall back and pass in the cmd2 app -* Other - * Added missing doc-string for new cmd2.Cmd __init__ parameters +- Other + - Added missing doc-string for new cmd2.Cmd **init** parameters introduced by CommandSet enhancement ## 1.3.2 (August 10, 2020) -* Bug Fixes - * Fixed `prog` value of subcommands added with `as_subcommand_to()` decorator. - * Fixed missing settings in subcommand parsers created with `as_subcommand_to()` decorator. These settings + +- Bug Fixes + - Fixed `prog` value of subcommands added with `as_subcommand_to()` decorator. + - Fixed missing settings in subcommand parsers created with `as_subcommand_to()` decorator. These settings include things like description and epilog text. - * Fixed issue with CommandSet auto-discovery only searching direct sub-classes -* Enhancements - * Added functions to fetch registered CommandSets by type and command name + - Fixed issue with CommandSet auto-discovery only searching direct sub-classes +- Enhancements + - Added functions to fetch registered CommandSets by type and command name ## 1.3.1 (August 6, 2020) -* Bug Fixes - * Fixed issue determining whether an argparse completer function required a reference to a containing + +- Bug Fixes + - Fixed issue determining whether an argparse completer function required a reference to a containing CommandSet. Also resolves issues determining the correct CommandSet instance when calling the argparse - argument completer function. Manifested as a TypeError when using `cmd2.Cmd.path_complete` as a completer + argument completer function. Manifested as a TypeError when using `cmd2.Cmd.path_complete` as a completer for an argparse-based command defined in a CommandSet ## 1.3.0 (August 4, 2020) -* Enhancements - * Added CommandSet - Enables defining a separate loadable module of commands to register/unregister + +- Enhancements + - Added CommandSet - Enables defining a separate loadable module of commands to register/unregister with your cmd2 application. -* Other - * Marked with_argparser_and_unknown_args pending deprecation and consolidated implementation into +- Other + - Marked with_argparser_and_unknown_args pending deprecation and consolidated implementation into with_argparser ## 1.2.1 (July 14, 2020) -* Bug Fixes - * Relax minimum version of `importlib-metadata` to >= 1.6.0 when using Python < 3.8 + +- Bug Fixes + - Relax minimum version of `importlib-metadata` to >= 1.6.0 when using Python < 3.8 ## 1.2.0 (July 13, 2020) -* Bug Fixes - * Fixed `typing` module compatibility issue with Python 3.5 prior to 3.5.4 -* Enhancements - * Switched to getting version using `importlib.metadata` instead of using `pkg_resources` - * Improves `cmd2` application launch time on systems that have a lot of Python packages on `sys.path` - * Added dependency on `importlib_metadata` when running on versions of Python prior to 3.8 + +- Bug Fixes + - Fixed `typing` module compatibility issue with Python 3.5 prior to 3.5.4 +- Enhancements + - Switched to getting version using `importlib.metadata` instead of using `pkg_resources` + - Improves `cmd2` application launch time on systems that have a lot of Python packages on `sys.path` + - Added dependency on `importlib_metadata` when running on versions of Python prior to 3.8 ## 1.1.0 (June 6, 2020) -* Bug Fixes - * Fixed issue where subcommand usage text could contain a subcommand alias instead of the actual name - * Fixed bug in `ArgparseCompleter` where `fill_width` could become negative if `token_width` was large + +- Bug Fixes + - Fixed issue where subcommand usage text could contain a subcommand alias instead of the actual name + - Fixed bug in `ArgparseCompleter` where `fill_width` could become negative if `token_width` was large relative to the terminal width. -* Enhancements - * Made `ipy` consistent with `py` in the following ways - * `ipy` returns whether any of the commands run in it returned True to stop command loop - * `Cmd.in_pyscript()` returns True while in `ipy`. - * Starting `ipy` when `Cmd.in_pyscript()` is already True is not allowed. - * `with_argument_list`, `with_argparser`, and `with_argparser_and_unknown_args` wrappers now pass +- Enhancements + - Made `ipy` consistent with `py` in the following ways + - `ipy` returns whether any of the commands run in it returned True to stop command loop + - `Cmd.in_pyscript()` returns True while in `ipy`. + - Starting `ipy` when `Cmd.in_pyscript()` is already True is not allowed. + - `with_argument_list`, `with_argparser`, and `with_argparser_and_unknown_args` wrappers now pass `kwargs` through to their wrapped command function. - * Added `table_creator` module for creating richly formatted tables. This module is in beta and subject + - Added `table_creator` module for creating richly formatted tables. This module is in beta and subject to change. - * See [table_creation](https://cmd2.readthedocs.io/en/latest/features/table_creation.html) + - See [table_creation](https://cmd2.readthedocs.io/en/latest/features/table_creation.html) documentation for an overview. - * See [table_creation.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_creation.py) + - See [table_creation.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_creation.py) for an example. - * Added the following exceptions to the public API - * `SkipPostcommandHooks` - Custom exception class for when a command has a failure bad enough to skip + - Added the following exceptions to the public API + - `SkipPostcommandHooks` - Custom exception class for when a command has a failure bad enough to skip post command hooks, but not bad enough to print the exception to the user. - * `Cmd2ArgparseError` - A `SkipPostcommandHooks` exception for when a command fails to parse its arguments. + - `Cmd2ArgparseError` - A `SkipPostcommandHooks` exception for when a command fails to parse its arguments. Normally argparse raises a `SystemExit` exception in these cases. To avoid stopping the command loop, catch the `SystemExit` and raise this instead. If you still need to run post command hooks after parsing fails, just return instead of raising an exception. - * Added explicit handling of `SystemExit`. If a command raises this exception, the command loop will be + - Added explicit handling of `SystemExit`. If a command raises this exception, the command loop will be gracefully stopped. ## 1.0.2 (April 06, 2020) -* Bug Fixes - * Ctrl-C now stops a running text script instead of just the current `run_script` command -* Enhancements - * `do_shell()` now saves the return code of the command it runs in `self.last_result` for use in pyscripts + +- Bug Fixes + - Ctrl-C now stops a running text script instead of just the current `run_script` command +- Enhancements + - `do_shell()` now saves the return code of the command it runs in `self.last_result` for use in pyscripts ## 1.0.1 (March 13, 2020) -* Bug Fixes - * Fixed issue where postcmd hooks were running after an `argparse` exception in a command. + +- Bug Fixes + - Fixed issue where postcmd hooks were running after an `argparse` exception in a command. ## 1.0.0 (March 1, 2020) -* Enhancements - * The documentation at [cmd2.rftd.io](https://cmd2.readthedocs.io) received a major overhaul -* Other - * Moved [categorize](https://cmd2.readthedocs.io/en/latest/api/utils.html#miscellaneous) utility function from **decorators** module to **utils** module -* Notes - * Now that the 1.0 release is out, `cmd2` intends to follow [Semantic Versioning](https://semver.org) + +- Enhancements + - The documentation at [cmd2.rftd.io](https://cmd2.readthedocs.io) received a major overhaul +- Other + - Moved [categorize](https://cmd2.readthedocs.io/en/latest/api/utils.html#miscellaneous) utility function from **decorators** module to **utils** module +- Notes + - Now that the 1.0 release is out, `cmd2` intends to follow [Semantic Versioning](https://semver.org) ## 0.10.1 (February 19, 2020) -* Bug Fixes - * Corrected issue where the actual new value was not always being printed in do_set. This occurred in cases where + +- Bug Fixes + - Corrected issue where the actual new value was not always being printed in do_set. This occurred in cases where the typed value differed from what the setter had converted it to. - * Fixed bug where ANSI style sequences were not correctly handled in `utils.truncate_line()`. - * Fixed bug where pyscripts could edit `cmd2.Cmd.py_locals` dictionary. - * Fixed bug where cmd2 set `sys.path[0]` for a pyscript to cmd2's working directory instead of the - script file's directory. - * Fixed bug where `sys.path` was not being restored after a pyscript ran. -* Enhancements - * Renamed set command's `-l/--long` flag to `-v/--verbose` for consistency with help and history commands. - * Setting the following pyscript variables: - * `__name__`: __main__ - * `__file__`: script path (as typed, ~ will be expanded) - * Only tab complete after redirection tokens if redirection is allowed - * Made `CompletionError` exception available to non-argparse tab completion - * Added `apply_style` to `CompletionError` initializer. It defaults to True, but can be set to False if - you don't want the error text to have `ansi.style_error()` applied to it when printed. -* Other - * Removed undocumented `py run` command since it was replaced by `run_pyscript` a while ago - * Renamed `AutoCompleter` to `ArgparseCompleter` for clarity - * Custom `EmptyStatement` exception is no longer part of the documented public API -* Notes - * This is a beta release leading up to the 1.0.0 release - * We intend no more breaking changes prior to 1.0.0 - * Just bug fixes, documentation updates, and enhancements + - Fixed bug where ANSI style sequences were not correctly handled in `utils.truncate_line()`. + - Fixed bug where pyscripts could edit `cmd2.Cmd.py_locals` dictionary. + - Fixed bug where cmd2 set `sys.path[0]` for a pyscript to cmd2's working directory instead of the + script file's directory. + - Fixed bug where `sys.path` was not being restored after a pyscript ran. +- Enhancements + - Renamed set command's `-l/--long` flag to `-v/--verbose` for consistency with help and history commands. + - Setting the following pyscript variables: + - `__name__`: **main** + - `__file__`: script path (as typed, ~ will be expanded) + - Only tab complete after redirection tokens if redirection is allowed + - Made `CompletionError` exception available to non-argparse tab completion + - Added `apply_style` to `CompletionError` initializer. It defaults to True, but can be set to False if + you don't want the error text to have `ansi.style_error()` applied to it when printed. +- Other + - Removed undocumented `py run` command since it was replaced by `run_pyscript` a while ago + - Renamed `AutoCompleter` to `ArgparseCompleter` for clarity + - Custom `EmptyStatement` exception is no longer part of the documented public API +- Notes + - This is a beta release leading up to the 1.0.0 release + - We intend no more breaking changes prior to 1.0.0 + - Just bug fixes, documentation updates, and enhancements ## 0.10.0 (February 7, 2020) -* Enhancements - * Changed the default help text to make `help -v` more discoverable - * **set** command now supports tab completion of values - * Added `add_settable()` and `remove_settable()` convenience methods to update `self.settable` dictionary - * Added convenience `ansi.fg` and `ansi.bg` enums of foreground and background colors - * `ansi.style()` `fg` argument can now either be of type `str` or `ansi.fg` - * `ansi.style()` `bg` argument can now either be of type `str` or `ansi.bg` - * This supports IDE auto-completion of color names - * The enums also support - * `f-strings` and `format()` calls (e.g. `"{}hello{}".format(fg.blue, fg.reset)`) - * string concatenation (e.g. `fg.blue + "hello" + fg.reset`) -* Breaking changes - * Renamed `locals_in_py` attribute of `cmd2.Cmd` to `self_in_py` - * The following public attributes of `cmd2.Cmd` are no longer settable at runtime by default: - * `continuation_prompt` - * `self_in_py` - * `prompt` - * `self.settable` changed to `self.settables` - * It is now a Dict[str, Settable] instead of Dict[str, str] - * setting onchange callbacks have a new method signature and must be added to the + +- Enhancements + - Changed the default help text to make `help -v` more discoverable + - **set** command now supports tab completion of values + - Added `add_settable()` and `remove_settable()` convenience methods to update `self.settable` dictionary + - Added convenience `ansi.fg` and `ansi.bg` enums of foreground and background colors + - `ansi.style()` `fg` argument can now either be of type `str` or `ansi.fg` + - `ansi.style()` `bg` argument can now either be of type `str` or `ansi.bg` + - This supports IDE auto-completion of color names + - The enums also support + - `f-strings` and `format()` calls (e.g. `"{}hello{}".format(fg.blue, fg.reset)`) + - string concatenation (e.g. `fg.blue + "hello" + fg.reset`) +- Breaking changes + - Renamed `locals_in_py` attribute of `cmd2.Cmd` to `self_in_py` + - The following public attributes of `cmd2.Cmd` are no longer settable at runtime by default: + - `continuation_prompt` + - `self_in_py` + - `prompt` + - `self.settable` changed to `self.settables` + - It is now a Dict[str, Settable] instead of Dict[str, str] + - setting onchange callbacks have a new method signature and must be added to the Settable instance in order to be called - * Removed `cast()` utility function - * Removed `ansi.FG_COLORS` and `ansi.BG_COLORS` dictionaries - * Replaced with `ansi.fg` and `ansi.bg` enums providing similar but improved functionality -* Notes - * This is an alpha release leading up to the 1.0.0 release - * We intend no more breaking changes prior to 1.0.0 - * Just bug fixes, documentation updates, and enhancements + - Removed `cast()` utility function + - Removed `ansi.FG_COLORS` and `ansi.BG_COLORS` dictionaries + - Replaced with `ansi.fg` and `ansi.bg` enums providing similar but improved functionality +- Notes + - This is an alpha release leading up to the 1.0.0 release + - We intend no more breaking changes prior to 1.0.0 + - Just bug fixes, documentation updates, and enhancements ## 0.9.25 (January 26, 2020) -* Enhancements - * Reduced what gets put in package downloadable from PyPI (removed irrelevant CI config files and such) + +- Enhancements + - Reduced what gets put in package downloadable from PyPI (removed irrelevant CI config files and such) ## 0.9.24 (January 23, 2020) -* Enhancements - * Flushing stderr when setting the window title and printing alerts for better responsiveness in cases where - stderr is not unbuffered. - * Added function to truncate a single line to fit within a given display width. `cmd2.utils.truncate_line` - supports characters with display widths greater than 1 and ANSI style sequences. - * Added line truncation support to `cmd2.utils` text alignment functions. - * Added support for Python 3.9 alpha + +- Enhancements + - Flushing stderr when setting the window title and printing alerts for better responsiveness in cases where + stderr is not unbuffered. + - Added function to truncate a single line to fit within a given display width. `cmd2.utils.truncate_line` + supports characters with display widths greater than 1 and ANSI style sequences. + - Added line truncation support to `cmd2.utils` text alignment functions. + - Added support for Python 3.9 alpha ## 0.9.23 (January 9, 2020) -* Bug Fixes - * Fixed bug where startup script containing a single quote in its file name was incorrectly quoted - * Added missing implicit dependency on `setuptools` due to build with `setuptools_scm` -* Enhancements - * Added dim text style support via `style()` function and `ansi.INTENSITY_DIM` setting. -* Breaking changes - * Renamed the following `ansi` members for accuracy in what types of ANSI escape sequences are handled - * `ansi.allow_ansi` -> `ansi.allow_style` - * `ansi.ansi_safe_wcswidth()` -> `ansi.style_aware_wcswidth()` - * `ansi.ansi_aware_write()` -> `ansi.style_aware_write()` - * Renamed the following `ansi` members for clarification - * `ansi.BRIGHT` -> `ansi.INTENSITY_BRIGHT` - * `ansi.NORMAL` -> `ansi.INTENSITY_NORMAL` + +- Bug Fixes + - Fixed bug where startup script containing a single quote in its file name was incorrectly quoted + - Added missing implicit dependency on `setuptools` due to build with `setuptools_scm` +- Enhancements + - Added dim text style support via `style()` function and `ansi.INTENSITY_DIM` setting. +- Breaking changes + - Renamed the following `ansi` members for accuracy in what types of ANSI escape sequences are handled + - `ansi.allow_ansi` -> `ansi.allow_style` + - `ansi.ansi_safe_wcswidth()` -> `ansi.style_aware_wcswidth()` + - `ansi.ansi_aware_write()` -> `ansi.style_aware_write()` + - Renamed the following `ansi` members for clarification + - `ansi.BRIGHT` -> `ansi.INTENSITY_BRIGHT` + - `ansi.NORMAL` -> `ansi.INTENSITY_NORMAL` ## 0.9.22 (December 9, 2019) -* Bug Fixes - * Fixed bug where a redefined `ansi.style_error` was not being used in all `cmd2` files -* Enhancements - * Enabled line buffering when redirecting output to a file - * Added `align_left()`, `align_center()`, and `align_right()` to utils.py. All 3 of these functions support - ANSI escape sequences and characters with display widths greater than 1. They wrap `align_text()` which - is also in utils.py. + +- Bug Fixes + - Fixed bug where a redefined `ansi.style_error` was not being used in all `cmd2` files +- Enhancements + - Enabled line buffering when redirecting output to a file + - Added `align_left()`, `align_center()`, and `align_right()` to utils.py. All 3 of these functions support + ANSI escape sequences and characters with display widths greater than 1. They wrap `align_text()` which + is also in utils.py. ## 0.9.21 (November 26, 2019) -* Bug Fixes - * Fixed bug where pipe processes were not being stopped by Ctrl-C - * Added exception handling to account for non-standard Python environments in which readline is not loaded - dynamically from a shared library file -* Enhancements - * Added `read_input()` function that is used to read from stdin. Unlike the Python built-in `input()`, it also has - an argument to disable tab completion while input is being entered. - * Added capability to override the argument parser class used by cmd2 built-in commands. See override_parser.py - example for more details. - * Added `end` argument to `pfeedback()` to be consistent with the other print functions like `poutput()`. - * Added `apply_style` to `pwarning()`. -* Breaking changes - * For consistency between all the print functions: - * Made `end` and `chop` keyword-only arguments of `ppaged()` - * `end` is always added to message in `ppaged()` + +- Bug Fixes + - Fixed bug where pipe processes were not being stopped by Ctrl-C + - Added exception handling to account for non-standard Python environments in which readline is not loaded + dynamically from a shared library file +- Enhancements + - Added `read_input()` function that is used to read from stdin. Unlike the Python built-in `input()`, it also has + an argument to disable tab completion while input is being entered. + - Added capability to override the argument parser class used by cmd2 built-in commands. See override_parser.py + example for more details. + - Added `end` argument to `pfeedback()` to be consistent with the other print functions like `poutput()`. + - Added `apply_style` to `pwarning()`. +- Breaking changes + - For consistency between all the print functions: + - Made `end` and `chop` keyword-only arguments of `ppaged()` + - `end` is always added to message in `ppaged()` ## 0.9.20 (November 12, 2019) -* Bug Fixes - * Fixed bug where setting `use_ipython` to False removed ipy command from the entire `cmd2.Cmd` class instead of - just the instance being created - * Fix bug where cmd2 ran 'stty sane' command when stdin was not a terminal -* Enhancements - * Send all startup script paths to run_script. Previously we didn't do this if the file was empty, but that - showed no record of the run_script command in history. - * Made it easier for developers to override `edit` command by having `do_history` no longer call `do_edit`. This - also removes the need to exclude `edit` command from history list. - * It is no longer necessary to set the `prog` attribute of an argparser with subcommands. cmd2 now automatically - sets the prog value of it and all its subparsers so that all usage statements contain the top level command name - and not sys.argv[0]. -* Breaking changes - * Some constants were moved from cmd2.py to constants.py - * cmd2 command decorators were moved to decorators.py. If you were importing them via cmd2's \_\_init\_\_.py, then - there will be no issues. + +- Bug Fixes + - Fixed bug where setting `use_ipython` to False removed ipy command from the entire `cmd2.Cmd` class instead of + just the instance being created + - Fix bug where cmd2 ran 'stty sane' command when stdin was not a terminal +- Enhancements + - Send all startup script paths to run_script. Previously we didn't do this if the file was empty, but that + showed no record of the run_script command in history. + - Made it easier for developers to override `edit` command by having `do_history` no longer call `do_edit`. This + also removes the need to exclude `edit` command from history list. + - It is no longer necessary to set the `prog` attribute of an argparser with subcommands. cmd2 now automatically + sets the prog value of it and all its subparsers so that all usage statements contain the top level command name + and not sys.argv[0]. +- Breaking changes + - Some constants were moved from cmd2.py to constants.py + - cmd2 command decorators were moved to decorators.py. If you were importing them via cmd2's \_\_init\_\_.py, then + there will be no issues. ## 0.9.19 (October 14, 2019) -* Bug Fixes - * Fixed `ValueError` exception which could occur when an old format persistent history file is loaded with new `cmd2` -* Enhancements - * Improved displaying multiline CompletionErrors by indenting all lines + +- Bug Fixes + - Fixed `ValueError` exception which could occur when an old format persistent history file is loaded with new `cmd2` +- Enhancements + - Improved displaying multiline CompletionErrors by indenting all lines ## 0.9.18 (October 1, 2019) -* Bug Fixes - * Fixed bug introduced in 0.9.17 where help functions for hidden and disabled commands were not being filtered - out as help topics -* Enhancements - * `AutoCompleter` now handles argparse's mutually exclusive groups. It will not tab complete flag names or positionals - for already completed groups. It also will print an error if you try tab completing a flag's value if the flag - belongs to a completed group. - * `AutoCompleter` now uses the passed-in parser's help formatter to generate hint text. This gives help and - hint text for an argument consistent formatting. + +- Bug Fixes + - Fixed bug introduced in 0.9.17 where help functions for hidden and disabled commands were not being filtered + out as help topics +- Enhancements + - `AutoCompleter` now handles argparse's mutually exclusive groups. It will not tab complete flag names or positionals + for already completed groups. It also will print an error if you try tab completing a flag's value if the flag + belongs to a completed group. + - `AutoCompleter` now uses the passed-in parser's help formatter to generate hint text. This gives help and + hint text for an argument consistent formatting. ## 0.9.17 (September 23, 2019) -* Bug Fixes - * Fixed a bug when using WSL when all Windows paths have been removed from $PATH - * Fixed a bug when running a cmd2 application on Linux without Gtk libraries installed -* Enhancements - * No longer treating empty text scripts as an error condition - * Allow dynamically extending a `cmd2.Cmd` object instance with a `do_xxx` method at runtime - * Choices/Completer functions can now be passed a dictionary that maps command-line tokens to their - argparse argument. This is helpful when one argument determines what is tab completed for another argument. - If these functions have an argument called `arg_tokens`, then AutoCompleter will automatically pass this - dictionary to them. - * Added CompletionError class that can be raised during argparse-based tab completion and printed to the user - * Added the following convenience methods + +- Bug Fixes + - Fixed a bug when using WSL when all Windows paths have been removed from $PATH + - Fixed a bug when running a cmd2 application on Linux without Gtk libraries installed +- Enhancements + - No longer treating empty text scripts as an error condition + - Allow dynamically extending a `cmd2.Cmd` object instance with a `do_xxx` method at runtime + - Choices/Completer functions can now be passed a dictionary that maps command-line tokens to their + argparse argument. This is helpful when one argument determines what is tab completed for another argument. + If these functions have an argument called `arg_tokens`, then AutoCompleter will automatically pass this + dictionary to them. + - Added CompletionError class that can be raised during argparse-based tab completion and printed to the user + - Added the following convenience methods - `Cmd.in_script()` - return whether a text script is running - `Cmd.in_pyscript()` - return whether a pyscript is running ## 0.9.16 (August 7, 2019) -* Bug Fixes - * Fixed inconsistent parsing/tab completion behavior based on the value of `allow_redirection`. This flag is - only meant to be a security setting that prevents redirection of stdout and should not alter parsing logic. -* Enhancements - * Raise `TypeError` if trying to set choices/completions on argparse action that accepts no arguments - * Create directory for the persistent history file if it does not already exist - * Added `set_choices_function()`, `set_choices_method()`, `set_completer_function()`, and `set_completer_method()` - to support cases where this functionality needs to be added to an argparse action outside of the normal - `parser.add_argument()` call. -* Breaking Changes - * Aliases and macros can no longer have the same name as a command + +- Bug Fixes + - Fixed inconsistent parsing/tab completion behavior based on the value of `allow_redirection`. This flag is + only meant to be a security setting that prevents redirection of stdout and should not alter parsing logic. +- Enhancements + - Raise `TypeError` if trying to set choices/completions on argparse action that accepts no arguments + - Create directory for the persistent history file if it does not already exist + - Added `set_choices_function()`, `set_choices_method()`, `set_completer_function()`, and `set_completer_method()` + to support cases where this functionality needs to be added to an argparse action outside of the normal + `parser.add_argument()` call. +- Breaking Changes + - Aliases and macros can no longer have the same name as a command ## 0.9.15 (July 24, 2019) -* Bug Fixes - * Fixed exception caused by tab completing after an invalid subcommand was entered - * Fixed bug where `history -v` was sometimes showing raw and expanded commands when they weren't different - * Fixed bug where multiline commands were having leading and ending spaces stripped. This would mess up quoted - strings that crossed multiple lines. - * Fixed a bug when appending to the clipboard where contents were in reverse order - * Fixed issue where run_pyscript failed if the script's filename had 2 or more consecutive spaces - * Fixed issue where completer function of disabled command would still run -* Enhancements - * Greatly simplified using argparse-based tab completion. The new interface is a complete overhaul that breaks - the previous way of specifying completion and choices functions. See header of [argparse_custom.py](https://github.com/python-cmd2/cmd2/blob/master/cmd2/argparse_custom.py) - for more information. - * Enabled tab completion on multiline commands -* **Renamed Commands Notice** - * The following commands were renamed in the last release and have been removed in this release - * `load` - replaced by `run_script` - * `_relative_load` - replaced by `_relative_run_script` - * `pyscript` - replaced by `run_pyscript` - * We apologize for any inconvenience, but the new names are more self-descriptive - * Lots of end users were confused particularly about what exactly `load` should be loading -* Breaking Changes - * Restored `cmd2.Cmd.statement_parser` to be a public attribute (no underscore) - * Since it can be useful for creating [post-parsing hooks](https://cmd2.readthedocs.io/en/latest/features/hooks.html#postparsing-hooks) - * Completely overhauled the interface for adding tab completion to argparse arguments. See enhancements for more details. - * `ACArgumentParser` is now called `Cmd2ArgumentParser` - * Moved `basic_complete` to utils.py - * Made optional arguments on the following completer methods keyword-only: - `delimiter_complete`, `flag_based_complete`, `index_based_complete`, `path_complete`, `shell_cmd_complete` - * Renamed history option from `--output-file` to `--output_file` - * Renamed `matches_sort_key` to `default_sort_key`. This value determines the default sort ordering of string - results like alias, command, category, macro, settable, and shortcut names. Unsorted tab completion results - also are sorted with this key. Its default value (ALPHABETICAL_SORT_KEY) performs a case-insensitive alphabetical - sort, but it can be changed to a natural sort by setting the value to NATURAL_SORT_KEY. - * `StatementParser` now expects shortcuts to be passed in as dictionary. This eliminates the step of converting the - shortcuts dictionary into a tuple before creating `StatementParser`. - * Renamed `Cmd.pyscript_name` to `Cmd.py_bridge_name` - * Renamed `Cmd.pystate` to `Cmd.py_locals` - * Renamed `PyscriptBridge` to `PyBridge` + +- Bug Fixes + - Fixed exception caused by tab completing after an invalid subcommand was entered + - Fixed bug where `history -v` was sometimes showing raw and expanded commands when they weren't different + - Fixed bug where multiline commands were having leading and ending spaces stripped. This would mess up quoted + strings that crossed multiple lines. + - Fixed a bug when appending to the clipboard where contents were in reverse order + - Fixed issue where run_pyscript failed if the script's filename had 2 or more consecutive spaces + - Fixed issue where completer function of disabled command would still run +- Enhancements + - Greatly simplified using argparse-based tab completion. The new interface is a complete overhaul that breaks + the previous way of specifying completion and choices functions. See header of [argparse_custom.py](https://github.com/python-cmd2/cmd2/blob/master/cmd2/argparse_custom.py) + for more information. + - Enabled tab completion on multiline commands +- **Renamed Commands Notice** + - The following commands were renamed in the last release and have been removed in this release + - `load` - replaced by `run_script` + - `_relative_load` - replaced by `_relative_run_script` + - `pyscript` - replaced by `run_pyscript` + - We apologize for any inconvenience, but the new names are more self-descriptive + - Lots of end users were confused particularly about what exactly `load` should be loading +- Breaking Changes + - Restored `cmd2.Cmd.statement_parser` to be a public attribute (no underscore) + - Since it can be useful for creating [post-parsing hooks](https://cmd2.readthedocs.io/en/latest/features/hooks.html#postparsing-hooks) + - Completely overhauled the interface for adding tab completion to argparse arguments. See enhancements for more details. + - `ACArgumentParser` is now called `Cmd2ArgumentParser` + - Moved `basic_complete` to utils.py + - Made optional arguments on the following completer methods keyword-only: + `delimiter_complete`, `flag_based_complete`, `index_based_complete`, `path_complete`, `shell_cmd_complete` + - Renamed history option from `--output-file` to `--output_file` + - Renamed `matches_sort_key` to `default_sort_key`. This value determines the default sort ordering of string + results like alias, command, category, macro, settable, and shortcut names. Unsorted tab completion results + also are sorted with this key. Its default value (ALPHABETICAL_SORT_KEY) performs a case-insensitive alphabetical + sort, but it can be changed to a natural sort by setting the value to NATURAL_SORT_KEY. + - `StatementParser` now expects shortcuts to be passed in as dictionary. This eliminates the step of converting the + shortcuts dictionary into a tuple before creating `StatementParser`. + - Renamed `Cmd.pyscript_name` to `Cmd.py_bridge_name` + - Renamed `Cmd.pystate` to `Cmd.py_locals` + - Renamed `PyscriptBridge` to `PyBridge` ## 0.9.14 (June 29, 2019) -* Enhancements - * Added support for and testing with Python 3.8, starting with 3.8 beta - * Improved information displayed during transcript testing - * Added `ansi` module with functions and constants to support ANSI escape sequences which are used for things - like applying style to text - * Added support for applying styles (color, bold, underline) to text via `style()` function in `ansi` module - * Added default styles to ansi.py for printing `success`, `warning`. and `error` text. These are the styles used - by cmd2 and can be overridden to match the color scheme of your application. - * Added `ansi_aware_write()` function to `ansi` module. This function takes into account the value of `allow_ansi` - to determine if ANSI escape sequences should be stripped when not writing to a tty. See documentation for more - information on the `allow_ansi` setting. -* Breaking Changes - * Python 3.4 reached its [end of life](https://www.python.org/dev/peps/pep-0429/) on March 18, 2019 and is no longer supported by `cmd2` - * If you need to use Python 3.4, you should pin your requirements to use `cmd2` 0.9.13 - * Made lots of changes to minimize the public API of the `cmd2.Cmd` class - * Attributes and methods we do not intend to be public now all begin with an underscore - * We make no API stability guarantees about these internal functions - * Split `perror` into 2 functions: - * `perror` - print a message to sys.stderr - * `pexcept` - print Exception message to sys.stderr. If debug is true, print exception traceback if one exists - * Signature of `poutput` and `perror` significantly changed - * Removed color parameters `color`, `err_color`, and `war_color` from `poutput` and `perror` - * See the docstrings of these methods or the [cmd2 docs](https://cmd2.readthedocs.io/en/latest/features/generating_output.html) for more info on applying styles to output messages - * `end` argument is now keyword-only and cannot be specified positionally - * `traceback_war` no longer exists as an argument since it isn't needed now that `perror` and `pexcept` exist - * Moved `cmd2.Cmd.colors` to ansi.py and renamed it to `allow_ansi`. This is now an application-wide setting. - * Renamed the following constants and moved them to ansi.py - * `COLORS_ALWAYS` --> `ANSI_ALWAYS` - * `COLORS_NEVER` --> `ANSI_NEVER` - * `COLORS_TERMINAL` --> `ANSI_TERMINAL` -* **Renamed Commands Notice** - * The following commands have been renamed. The old names will be supported until the next release. - * `load` --> `run_script` - * `_relative_load` --> `_relative_run_script` - * `pyscript` --> `run_pyscript` + +- Enhancements + - Added support for and testing with Python 3.8, starting with 3.8 beta + - Improved information displayed during transcript testing + - Added `ansi` module with functions and constants to support ANSI escape sequences which are used for things + like applying style to text + - Added support for applying styles (color, bold, underline) to text via `style()` function in `ansi` module + - Added default styles to ansi.py for printing `success`, `warning`. and `error` text. These are the styles used + by cmd2 and can be overridden to match the color scheme of your application. + - Added `ansi_aware_write()` function to `ansi` module. This function takes into account the value of `allow_ansi` + to determine if ANSI escape sequences should be stripped when not writing to a tty. See documentation for more + information on the `allow_ansi` setting. +- Breaking Changes + - Python 3.4 reached its [end of life](https://www.python.org/dev/peps/pep-0429/) on March 18, 2019 and is no longer supported by `cmd2` + - If you need to use Python 3.4, you should pin your requirements to use `cmd2` 0.9.13 + - Made lots of changes to minimize the public API of the `cmd2.Cmd` class + - Attributes and methods we do not intend to be public now all begin with an underscore + - We make no API stability guarantees about these internal functions + - Split `perror` into 2 functions: + - `perror` - print a message to sys.stderr + - `pexcept` - print Exception message to sys.stderr. If debug is true, print exception traceback if one exists + - Signature of `poutput` and `perror` significantly changed + - Removed color parameters `color`, `err_color`, and `war_color` from `poutput` and `perror` + - See the docstrings of these methods or the [cmd2 docs](https://cmd2.readthedocs.io/en/latest/features/generating_output.html) for more info on applying styles to output messages + - `end` argument is now keyword-only and cannot be specified positionally + - `traceback_war` no longer exists as an argument since it isn't needed now that `perror` and `pexcept` exist + - Moved `cmd2.Cmd.colors` to ansi.py and renamed it to `allow_ansi`. This is now an application-wide setting. + - Renamed the following constants and moved them to ansi.py + - `COLORS_ALWAYS` --> `ANSI_ALWAYS` + - `COLORS_NEVER` --> `ANSI_NEVER` + - `COLORS_TERMINAL` --> `ANSI_TERMINAL` +- **Renamed Commands Notice** + - The following commands have been renamed. The old names will be supported until the next release. + - `load` --> `run_script` + - `_relative_load` --> `_relative_run_script` + - `pyscript` --> `run_pyscript` ## 0.9.13 (June 14, 2019) -* Bug Fixes - * Fixed issue where the wrong terminator was being appended by `Statement.expanded_command_line()` - * Fixed issue where aliases and macros could not contain terminator characters in their values - * History now shows what was typed for macros and not the resolved value by default. This is consistent with - the behavior of aliases. Use the `expanded` or `verbose` arguments to `history` to see the resolved value for - the macro. - * Fixed parsing issue in case where output redirection appears before a pipe. In that case, the pipe was given - precedence even though it appeared later in the command. - * Fixed issue where quotes around redirection file paths were being lost in `Statement.expanded_command_line()` - * Fixed a bug in how line numbers were calculated for transcript testing - * Fixed issue where `_cmdloop()` suppressed exceptions by returning from within its `finally` code - * Fixed UnsupportedOperation on fileno error when a shell command was one of the commands run while generating - a transcript - * Fixed bug where history was displaying expanded multiline commands when -x was not specified -* Enhancements - * **Added capability to chain pipe commands and redirect their output (e.g. !ls -l | grep user | wc -l > out.txt)** - * `pyscript` limits a command's stdout capture to the same period that redirection does. - Therefore output from a command's postparsing and finalization hooks isn't saved in the StdSim object. - * `StdSim.buffer.write()` now flushes when the wrapped stream uses line buffering and the bytes being written - contain a newline or carriage return. This helps when `pyscript` is echoing the output of a shell command - since the output will print at the same frequency as when the command is run in a terminal. - * **ACArgumentParser** no longer prints complete help text when a parsing error occurs since long help messages - scroll the actual error message off the screen. - * Exceptions occurring in tab completion functions are now printed to stderr before returning control back to - readline. This makes debugging a lot easier since readline suppresses these exceptions. - * Added support for custom Namespaces in the argparse decorators. See description of `ns_provider` argument - for more information. - * Transcript testing now sets the `exit_code` returned from `cmdloop` based on Success/Failure - * The history of entered commands previously was saved using the readline persistence mechanism, - and only persisted if you had readline installed. Now history is persisted independent of readline; user - input from previous invocations of `cmd2` based apps now shows in the `history` command. - * Text scripts now run immediately instead of adding their commands to `cmdqueue`. This allows easy capture of - the entire script's output. - * Added member to `CommandResult` called `stop` which is the return value of `onecmd_plus_hooks` after it runs - the given command line. -* Breaking changes - * Replaced `unquote_redirection_tokens()` with `unquote_specific_tokens()`. This was to support the fix - that allows terminators in alias and macro values. - * Changed `Statement.pipe_to` to a string instead of a list - * `preserve_quotes` is now a keyword-only argument in the argparse decorators - * Refactored so that `cmd2.Cmd.cmdloop()` returns the `exit_code` instead of a call to `sys.exit()` - It is now application developer's responsibility to treat the return value from `cmdloop()` accordingly - * Only valid commands are persistent in history between invocations of `cmd2` based apps. Previously - all user input was persistent in history. If readline is installed, the history available with the up and - down arrow keys (readline history) may not match that shown in the `history` command, because `history` - only tracks valid input, while readline history captures all input. - * History is now persisted in a binary format, not plain text format. Previous history files are destroyed - on first launch of a `cmd2` based app of version 0.9.13 or higher. - * HistoryItem class is no longer a subclass of `str`. If you are directly accessing the `.history` attribute - of a `cmd2` based app, you will need to update your code to use `.history.get(1).statement.raw` instead. - * Removed internally used `eos` command that was used to keep track of when a text script's commands ended - * Removed `cmd2` member called `_STOP_AND_EXIT` since it was just a boolean value that should always be True - * Removed `cmd2` member called `_should_quit` since `PyBridge` now handles this logic - * Removed support for `cmd.cmdqueue` - * `allow_cli_args` is now an argument to __init__ instead of a `cmd2` class member -* **Python 3.4 EOL notice** - * Python 3.4 reached its [end of life](https://www.python.org/dev/peps/pep-0429/) on March 18, 2019 - * This is the last release of `cmd2` which will support Python 3.4 + +- Bug Fixes + - Fixed issue where the wrong terminator was being appended by `Statement.expanded_command_line()` + - Fixed issue where aliases and macros could not contain terminator characters in their values + - History now shows what was typed for macros and not the resolved value by default. This is consistent with + the behavior of aliases. Use the `expanded` or `verbose` arguments to `history` to see the resolved value for + the macro. + - Fixed parsing issue in case where output redirection appears before a pipe. In that case, the pipe was given + precedence even though it appeared later in the command. + - Fixed issue where quotes around redirection file paths were being lost in `Statement.expanded_command_line()` + - Fixed a bug in how line numbers were calculated for transcript testing + - Fixed issue where `_cmdloop()` suppressed exceptions by returning from within its `finally` code + - Fixed UnsupportedOperation on fileno error when a shell command was one of the commands run while generating + a transcript + - Fixed bug where history was displaying expanded multiline commands when -x was not specified +- Enhancements + - **Added capability to chain pipe commands and redirect their output (e.g. !ls -l | grep user | wc -l > out.txt)** + - `pyscript` limits a command's stdout capture to the same period that redirection does. + Therefore output from a command's postparsing and finalization hooks isn't saved in the StdSim object. + - `StdSim.buffer.write()` now flushes when the wrapped stream uses line buffering and the bytes being written + contain a newline or carriage return. This helps when `pyscript` is echoing the output of a shell command + since the output will print at the same frequency as when the command is run in a terminal. + - **ACArgumentParser** no longer prints complete help text when a parsing error occurs since long help messages + scroll the actual error message off the screen. + - Exceptions occurring in tab completion functions are now printed to stderr before returning control back to + readline. This makes debugging a lot easier since readline suppresses these exceptions. + - Added support for custom Namespaces in the argparse decorators. See description of `ns_provider` argument + for more information. + - Transcript testing now sets the `exit_code` returned from `cmdloop` based on Success/Failure + - The history of entered commands previously was saved using the readline persistence mechanism, + and only persisted if you had readline installed. Now history is persisted independent of readline; user + input from previous invocations of `cmd2` based apps now shows in the `history` command. + - Text scripts now run immediately instead of adding their commands to `cmdqueue`. This allows easy capture of + the entire script's output. + - Added member to `CommandResult` called `stop` which is the return value of `onecmd_plus_hooks` after it runs + the given command line. +- Breaking changes + - Replaced `unquote_redirection_tokens()` with `unquote_specific_tokens()`. This was to support the fix + that allows terminators in alias and macro values. + - Changed `Statement.pipe_to` to a string instead of a list + - `preserve_quotes` is now a keyword-only argument in the argparse decorators + - Refactored so that `cmd2.Cmd.cmdloop()` returns the `exit_code` instead of a call to `sys.exit()` + It is now application developer's responsibility to treat the return value from `cmdloop()` accordingly + - Only valid commands are persistent in history between invocations of `cmd2` based apps. Previously + all user input was persistent in history. If readline is installed, the history available with the up and + down arrow keys (readline history) may not match that shown in the `history` command, because `history` + only tracks valid input, while readline history captures all input. + - History is now persisted in a binary format, not plain text format. Previous history files are destroyed + on first launch of a `cmd2` based app of version 0.9.13 or higher. + - HistoryItem class is no longer a subclass of `str`. If you are directly accessing the `.history` attribute + of a `cmd2` based app, you will need to update your code to use `.history.get(1).statement.raw` instead. + - Removed internally used `eos` command that was used to keep track of when a text script's commands ended + - Removed `cmd2` member called `_STOP_AND_EXIT` since it was just a boolean value that should always be True + - Removed `cmd2` member called `_should_quit` since `PyBridge` now handles this logic + - Removed support for `cmd.cmdqueue` + - `allow_cli_args` is now an argument to **init** instead of a `cmd2` class member +- **Python 3.4 EOL notice** + - Python 3.4 reached its [end of life](https://www.python.org/dev/peps/pep-0429/) on March 18, 2019 + - This is the last release of `cmd2` which will support Python 3.4 ## 0.9.12 (April 22, 2019) -* Bug Fixes - * Fixed a bug in how redirection and piping worked inside ``py`` or ``pyscript`` commands - * Fixed bug in `async_alert` where it didn't account for prompts that contained newline characters - * Fixed path completion case when CWD is just a slash. Relative path matches were incorrectly prepended with a slash. -* Enhancements - * Added ability to include command name placeholders in the message printed when trying to run a disabled command. - * See docstring for ``disable_command()`` or ``disable_category()`` for more details. - * Added instance attributes to customize error messages without having to override methods. These messages can - also be colored. - * `help_error` - the error that prints when no help information can be found - * `default_error` - the error that prints when a non-existent command is run - * The `with_argparser` decorators now add the Statement object created when parsing the command line to the - `argparse.Namespace` object they pass to the `do_*` methods. It is stored in an attribute called `__statement__`. - This can be useful if a command function needs to know the command line for things like logging. - * Added a `-t` option to the `load` command for automatically generating a transcript based on a script file - * When in a **pyscript**, the stdout and stderr streams of shell commands and processes being piped to are now - captured and included in the ``CommandResult`` structure. -* Potentially breaking changes - * The following commands now write to stderr instead of stdout when printing an error. This will make catching - errors easier in pyscript. - * ``do_help()`` - when no help information can be found - * ``default()`` - in all cases since this is called when an invalid command name is run - * ``_report_disabled_command_usage()`` - in all cases since this is called when a disabled command is run - * Removed *** from beginning of error messages printed by `do_help()` and `default()` - * Significantly refactored ``cmd.Cmd`` class so that all class attributes got converted to instance attributes, also: - * Added ``allow_redirection``, ``terminators``, ``multiline_commands``, and ``shortcuts`` as optional arguments - to ``cmd2.Cmd.__init__()`` - * A few instance attributes were moved inside ``StatementParser`` and properties were created for accessing them - * ``self.pipe_proc`` is now called ``self.cur_pipe_proc_reader`` and is a ``ProcReader`` class. - * Shell commands and commands being piped to while in a *pyscript* will function as if their output is going - to a pipe and not a tty. This was necessary to be able to capture their output. - * Removed `reserved_words` class attribute due to lack of use - * Removed `keywords` instance attribute due to lack of use + +- Bug Fixes + - Fixed a bug in how redirection and piping worked inside `py` or `pyscript` commands + - Fixed bug in `async_alert` where it didn't account for prompts that contained newline characters + - Fixed path completion case when CWD is just a slash. Relative path matches were incorrectly prepended with a slash. +- Enhancements + - Added ability to include command name placeholders in the message printed when trying to run a disabled command. + - See docstring for `disable_command()` or `disable_category()` for more details. + - Added instance attributes to customize error messages without having to override methods. These messages can + also be colored. + _ `help_error` - the error that prints when no help information can be found + _ `default_error` - the error that prints when a non-existent command is run + - The `with_argparser` decorators now add the Statement object created when parsing the command line to the + `argparse.Namespace` object they pass to the `do_*` methods. It is stored in an attribute called `__statement__`. + This can be useful if a command function needs to know the command line for things like logging. + - Added a `-t` option to the `load` command for automatically generating a transcript based on a script file + - When in a **pyscript**, the stdout and stderr streams of shell commands and processes being piped to are now + captured and included in the `CommandResult` structure. +- Potentially breaking changes + - The following commands now write to stderr instead of stdout when printing an error. This will make catching + errors easier in pyscript. + _ `do_help()` - when no help information can be found + _ `default()` - in all cases since this is called when an invalid command name is run \* `_report_disabled_command_usage()` - in all cases since this is called when a disabled command is run + - Removed \*\*\* from beginning of error messages printed by `do_help()` and `default()` + - Significantly refactored `cmd.Cmd` class so that all class attributes got converted to instance attributes, also: + - Added `allow_redirection`, `terminators`, `multiline_commands`, and `shortcuts` as optional arguments + to `cmd2.Cmd.__init__()` + - A few instance attributes were moved inside `StatementParser` and properties were created for accessing them + - `self.pipe_proc` is now called `self.cur_pipe_proc_reader` and is a `ProcReader` class. + - Shell commands and commands being piped to while in a _pyscript_ will function as if their output is going + to a pipe and not a tty. This was necessary to be able to capture their output. + - Removed `reserved_words` class attribute due to lack of use + - Removed `keywords` instance attribute due to lack of use ## 0.9.11 (March 13, 2019) -* Bug Fixes - * Fixed bug in how **history** command deals with multiline commands when output to a script - * Fixed a bug when the ``with_argument_list`` decorator is called with the optional ``preserve_quotes`` argument - * Fix bug in ``perror()`` where it would try to print an exception Traceback even if none existed -* Enhancements - * Improvements to the **history** command - * Simplified the display format and made it more similar to **bash** - * Added **-x**, **--expanded** flag - * output expanded commands instead of entered command (expands aliases, macros, and shortcuts) - * Added **-v**, **--verbose** flag - * display history and include expanded commands if they differ from the typed command - * Added support for negative indices - * Added ``matches_sort_key`` to override the default way tab completion matches are sorted - * Added ``StdSim.pause_storage`` member which when True will cause ``StdSim`` to not save the output sent to it. - See documentation for ``CommandResult`` in ``pyscript_bridge.py`` for reasons pausing the storage can be useful. - * Added ability to disable/enable individual commands and entire categories of commands. When a command + +- Bug Fixes + - Fixed bug in how **history** command deals with multiline commands when output to a script + - Fixed a bug when the `with_argument_list` decorator is called with the optional `preserve_quotes` argument + - Fix bug in `perror()` where it would try to print an exception Traceback even if none existed +- Enhancements + - Improvements to the **history** command + - Simplified the display format and made it more similar to **bash** + - Added **-x**, **--expanded** flag + - output expanded commands instead of entered command (expands aliases, macros, and shortcuts) + - Added **-v**, **--verbose** flag + - display history and include expanded commands if they differ from the typed command + - Added support for negative indices + - Added `matches_sort_key` to override the default way tab completion matches are sorted + - Added `StdSim.pause_storage` member which when True will cause `StdSim` to not save the output sent to it. + See documentation for `CommandResult` in `pyscript_bridge.py` for reasons pausing the storage can be useful. + - Added ability to disable/enable individual commands and entire categories of commands. When a command is disabled, it will not show up in the help menu or tab complete. If a user tries to run the command or call help on it, a command-specific message supplied by the developer will be printed. The following commands were added to support this feature. - * ``enable_command()`` - * ``enable_category()`` - * ``disable_command()`` - * ``disable_category()`` -* Potentially breaking changes - * Made ``cmd2_app`` a positional and required argument of ``AutoCompleter`` since certain functionality now - requires that it can't be ``None``. - * ``AutoCompleter`` no longer assumes ``CompletionItem`` results are sorted. Therefore you should follow the - ``cmd2`` convention of setting ``self.matches_sorted`` to True before returning the results if you have already - sorted the ``CompletionItem`` list. Otherwise it will be sorted using ``self.matches_sort_key``. - * Removed support for bash completion since this feature had slow performance. Also it relied on - ``AutoCompleter`` which has since developed a dependency on ``cmd2`` methods. - * Removed ability to call commands in ``pyscript`` as if they were functions (e.g. ``app.help()``) in favor - of only supporting one ``pyscript`` interface. This simplifies future maintenance. - * No longer supporting C-style comments. Hash (#) is the only valid comment marker. - * No longer supporting comments embedded in a command. Only command line input where the first - non-whitespace character is a # will be treated as a comment. This means any # character appearing - later in the command will be treated as a literal. The same applies to a # in the middle of a multiline - command, even if it is the first character on a line. - * \# this is a comment - * this # is not a comment + - `enable_command()` + - `enable_category()` + - `disable_command()` + - `disable_category()` +- Potentially breaking changes + - Made `cmd2_app` a positional and required argument of `AutoCompleter` since certain functionality now + requires that it can't be `None`. + - `AutoCompleter` no longer assumes `CompletionItem` results are sorted. Therefore you should follow the + `cmd2` convention of setting `self.matches_sorted` to True before returning the results if you have already + sorted the `CompletionItem` list. Otherwise it will be sorted using `self.matches_sort_key`. + - Removed support for bash completion since this feature had slow performance. Also it relied on + `AutoCompleter` which has since developed a dependency on `cmd2` methods. + - Removed ability to call commands in `pyscript` as if they were functions (e.g. `app.help()`) in favor + of only supporting one `pyscript` interface. This simplifies future maintenance. + - No longer supporting C-style comments. Hash (#) is the only valid comment marker. + - No longer supporting comments embedded in a command. Only command line input where the first + non-whitespace character is a # will be treated as a comment. This means any # character appearing + later in the command will be treated as a literal. The same applies to a # in the middle of a multiline + command, even if it is the first character on a line. + _ \# this is a comment + _ this # is not a comment ## 0.9.10 (February 22, 2019) -* Bug Fixes - * Fixed unit test that hangs on Windows + +- Bug Fixes + - Fixed unit test that hangs on Windows ## 0.9.9 (February 21, 2019) -* Bug Fixes - * Fixed bug where the ``set`` command was not tab completing from the current ``settable`` dictionary. -* Enhancements - * Changed edit command to use do_shell() instead of calling os.system() + +- Bug Fixes + - Fixed bug where the `set` command was not tab completing from the current `settable` dictionary. +- Enhancements + - Changed edit command to use do_shell() instead of calling os.system() ## 0.9.8 (February 06, 2019) -* Bug Fixes - * Fixed issue with echoing strings in StdSim. Because they were being sent to a binary buffer, line buffering - was being ignored. -* Enhancements - * Made quit() and exit() functions available to scripts run with pyscript. This allows those scripts to exit - back to the console's prompt instead of exiting the whole application. + +- Bug Fixes + - Fixed issue with echoing strings in StdSim. Because they were being sent to a binary buffer, line buffering + was being ignored. +- Enhancements + - Made quit() and exit() functions available to scripts run with pyscript. This allows those scripts to exit + back to the console's prompt instead of exiting the whole application. ## 0.9.7 (January 08, 2019) -* Bug Fixes - * Fixed bug when user chooses a zero or negative index when calling ``Cmd.select()`` - * Restored behavior where ``cmd_echo`` always starts as False in a py script. This was broken in 0.9.5. -* Enhancements - * **cmdloop** now only attempts to register a custom signal handler for SIGINT if running in the main thread - * commands run as a result of ``default_to_shell`` being **True** now run via ``do_shell()`` and are saved - to history. - * Added more tab completion to pyscript command. -* Deletions (potentially breaking changes) - * Deleted ``Cmd.colorize()`` and ``Cmd._colorcodes`` which were deprecated in 0.9.5 - * Replaced ``dir_exe_only`` and ``dir_only`` flags in ``path_complete`` with optional ``path_filter`` function - that is used to filter paths out of completion results. - * ``perror()`` no longer prepends "ERROR: " to the error message being printed + +- Bug Fixes + - Fixed bug when user chooses a zero or negative index when calling `Cmd.select()` + - Restored behavior where `cmd_echo` always starts as False in a py script. This was broken in 0.9.5. +- Enhancements + - **cmdloop** now only attempts to register a custom signal handler for SIGINT if running in the main thread + - commands run as a result of `default_to_shell` being **True** now run via `do_shell()` and are saved + to history. + - Added more tab completion to pyscript command. +- Deletions (potentially breaking changes) + - Deleted `Cmd.colorize()` and `Cmd._colorcodes` which were deprecated in 0.9.5 + - Replaced `dir_exe_only` and `dir_only` flags in `path_complete` with optional `path_filter` function + that is used to filter paths out of completion results. + - `perror()` no longer prepends "ERROR: " to the error message being printed ## 0.9.6 (October 13, 2018) -* Bug Fixes - * Fixed bug introduced in 0.9.5 caused by backing up and restoring `self.prompt` in `pseudo_raw_input`. + +- Bug Fixes + - Fixed bug introduced in 0.9.5 caused by backing up and restoring `self.prompt` in `pseudo_raw_input`. As part of this fix, continuation prompts will not be redrawn with `async_update_prompt` or `async_alert`. -* Enhancements - * All platforms now depend on [wcwidth](https://pypi.python.org/pypi/wcwidth) to assist with asynchronous alerts. - * Macros now accept extra arguments when called. These will be tacked onto the resolved command. - * All cmd2 commands run via `py` now go through `onecmd_plus_hooks`. +- Enhancements + - All platforms now depend on [wcwidth](https://pypi.python.org/pypi/wcwidth) to assist with asynchronous alerts. + - Macros now accept extra arguments when called. These will be tacked onto the resolved command. + - All cmd2 commands run via `py` now go through `onecmd_plus_hooks`. ## 0.9.5 (October 11, 2018) -* Bug Fixes - * Fixed bug where ``get_all_commands`` could return non-callable attributes - * Fixed bug where **alias** command was dropping quotes around arguments - * Fixed bug where running help on argparse commands didn't work if they didn't support -h - * Fixed transcript testing bug where last command in transcript has no expected output - * Fixed bugs with how AutoCompleter and ArgparseFunctor handle argparse - arguments with nargs=argparse.REMAINDER. Tab completion now correctly - matches how argparse will parse the values. Command strings generated by - ArgparseFunctor should now be compliant with how argparse expects - REMAINDER arguments to be ordered. - * Fixed bugs with how AutoCompleter handles flag prefixes. It is no - longer hard-coded to use '-' and will check against the prefix_chars in - the argparse object. Also, single-character tokens that happen to be a - prefix char are not treated as flags by argparse and AutoCompleter now - matches that behavior. - * Fixed bug where AutoCompleter was not distinguishing between a negative number and a flag - * Fixed bug where AutoCompleter did not handle -- the same way argparse does (all args after -- are non-options) -* Enhancements - * Added ``exit_code`` attribute of ``cmd2.Cmd`` class - * Enables applications to return a non-zero exit code when exiting from ``cmdloop`` - * ``ACHelpFormatter`` now inherits from ``argparse.RawTextHelpFormatter`` to make it easier - for formatting help/description text - * Aliases are now sorted alphabetically - * The **set** command now tab completes settable parameter names - * Added ``async_alert``, ``async_update_prompt``, and ``set_window_title`` functions - * These allow you to provide feedback to the user in an asynchronous fashion, meaning alerts can - display when the user is still entering text at the prompt. See [async_printing.py](https://github.com/python-cmd2/cmd2/blob/master/examples/async_printing.py) - for an example. - * Cross-platform colored output support - * ``colorama`` gets initialized properly in ``Cmd.__init()`` - * The ``Cmd.colors`` setting is no longer platform dependent and now has three values: - * Terminal (default) - output methods do not strip any ANSI escape sequences when output is a terminal, but - if the output is a pipe or a file the escape sequences are stripped - * Always - output methods **never** strip ANSI escape sequences, regardless of the output destination - * Never - output methods strip all ANSI escape sequences - * Added ``macro`` command to create macros, which are similar to aliases, but can take arguments when called - * All cmd2 command functions have been converted to use argparse. - * Renamed argparse_example.py to decorator_example.py to help clarify its intent -* Deprecations - * Deprecated the built-in ``cmd2`` support for colors including ``Cmd.colorize()`` and ``Cmd._colorcodes`` -* Deletions (potentially breaking changes) - * The ``preparse``, ``postparsing_precmd``, and ``postparsing_postcmd`` methods *deprecated* in the previous release - have been deleted - * The new application lifecycle hook system allows for registration of callbacks to be called at various points - in the lifecycle and is more powerful and flexible than the previous system - * ``alias`` is now a command with subcommands to create, list, and delete aliases. Therefore its syntax + +- Bug Fixes + - Fixed bug where `get_all_commands` could return non-callable attributes + - Fixed bug where **alias** command was dropping quotes around arguments + - Fixed bug where running help on argparse commands didn't work if they didn't support -h + - Fixed transcript testing bug where last command in transcript has no expected output + - Fixed bugs with how AutoCompleter and ArgparseFunctor handle argparse + arguments with nargs=argparse.REMAINDER. Tab completion now correctly + matches how argparse will parse the values. Command strings generated by + ArgparseFunctor should now be compliant with how argparse expects + REMAINDER arguments to be ordered. + - Fixed bugs with how AutoCompleter handles flag prefixes. It is no + longer hard-coded to use '-' and will check against the prefix_chars in + the argparse object. Also, single-character tokens that happen to be a + prefix char are not treated as flags by argparse and AutoCompleter now + matches that behavior. + - Fixed bug where AutoCompleter was not distinguishing between a negative number and a flag + - Fixed bug where AutoCompleter did not handle -- the same way argparse does (all args after -- are non-options) +- Enhancements + - Added `exit_code` attribute of `cmd2.Cmd` class + - Enables applications to return a non-zero exit code when exiting from `cmdloop` + - `ACHelpFormatter` now inherits from `argparse.RawTextHelpFormatter` to make it easier + for formatting help/description text + - Aliases are now sorted alphabetically + - The **set** command now tab completes settable parameter names + - Added `async_alert`, `async_update_prompt`, and `set_window_title` functions + - These allow you to provide feedback to the user in an asynchronous fashion, meaning alerts can + display when the user is still entering text at the prompt. See [async_printing.py](https://github.com/python-cmd2/cmd2/blob/master/examples/async_printing.py) + for an example. + - Cross-platform colored output support + - `colorama` gets initialized properly in `Cmd.__init()` + - The `Cmd.colors` setting is no longer platform dependent and now has three values: + - Terminal (default) - output methods do not strip any ANSI escape sequences when output is a terminal, but + if the output is a pipe or a file the escape sequences are stripped + - Always - output methods **never** strip ANSI escape sequences, regardless of the output destination + - Never - output methods strip all ANSI escape sequences + - Added `macro` command to create macros, which are similar to aliases, but can take arguments when called + - All cmd2 command functions have been converted to use argparse. + - Renamed argparse_example.py to decorator_example.py to help clarify its intent +- Deprecations + - Deprecated the built-in `cmd2` support for colors including `Cmd.colorize()` and `Cmd._colorcodes` +- Deletions (potentially breaking changes) + - The `preparse`, `postparsing_precmd`, and `postparsing_postcmd` methods _deprecated_ in the previous release + have been deleted \* The new application lifecycle hook system allows for registration of callbacks to be called at various points + in the lifecycle and is more powerful and flexible than the previous system + - `alias` is now a command with subcommands to create, list, and delete aliases. Therefore its syntax has changed. All current alias commands in startup scripts or transcripts will break with this release. - * `unalias` was deleted since ``alias delete`` replaced it + - `unalias` was deleted since `alias delete` replaced it ## 0.9.4 (August 21, 2018) -* Bug Fixes - * Fixed bug where ``preparse`` was not getting called - * Fixed bug in parsing of multiline commands where matching quote is on another line -* Enhancements - * Improved implementation of lifecycle hooks to support a plugin - framework, see ``docs/hooks.rst`` for details. - * New dependency on ``attrs`` third party module - * Added ``matches_sorted`` member to support custom sorting of tab completion matches - * Added [tab_autocomp_dynamic.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocomp_dynamic.py) example - * Demonstrates updating the argparse object during init instead of during class construction -* Deprecations - * Deprecated the following hook methods, see ``hooks.rst`` for full details: - * ``cmd2.Cmd.preparse()`` - equivalent functionality available - via ``cmd2.Cmd.register_postparsing_hook()`` - * ``cmd2.Cmd.postparsing_precmd()`` - equivalent functionality available - via ``cmd2.Cmd.register_postparsing_hook()`` - * ``cmd2.Cmd.postparsing_postcmd()`` - equivalent functionality available - via ``cmd2.Cmd.register_postcmd_hook()`` + +- Bug Fixes + - Fixed bug where `preparse` was not getting called + - Fixed bug in parsing of multiline commands where matching quote is on another line +- Enhancements + - Improved implementation of lifecycle hooks to support a plugin + framework, see `docs/hooks.rst` for details. + - New dependency on `attrs` third party module + - Added `matches_sorted` member to support custom sorting of tab completion matches + - Added [tab_autocomp_dynamic.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocomp_dynamic.py) example + - Demonstrates updating the argparse object during init instead of during class construction +- Deprecations + - Deprecated the following hook methods, see `hooks.rst` for full details: + - `cmd2.Cmd.preparse()` - equivalent functionality available + via `cmd2.Cmd.register_postparsing_hook()` + - `cmd2.Cmd.postparsing_precmd()` - equivalent functionality available + via `cmd2.Cmd.register_postparsing_hook()` + - `cmd2.Cmd.postparsing_postcmd()` - equivalent functionality available + via `cmd2.Cmd.register_postcmd_hook()` ## 0.8.9 (August 20, 2018) -* Bug Fixes - * Fixed extra slash that could print when tab completing users on Windows + +- Bug Fixes + - Fixed extra slash that could print when tab completing users on Windows ## 0.9.3 (July 12, 2018) -* Bug Fixes - * Fixed bug when StatementParser ``__init__()`` was called with ``terminators`` equal to ``None`` - * Fixed bug when ``Cmd.onecmd()`` was called with a raw ``str`` -* Enhancements - * Added ``--clear`` flag to ``history`` command that clears both the command and readline history. -* Deletions - * The ``CmdResult`` helper class which was *deprecated* in the previous release has now been deleted - * It has been replaced by the improved ``CommandResult`` class + +- Bug Fixes + - Fixed bug when StatementParser `__init__()` was called with `terminators` equal to `None` + - Fixed bug when `Cmd.onecmd()` was called with a raw `str` +- Enhancements + - Added `--clear` flag to `history` command that clears both the command and readline history. +- Deletions + - The `CmdResult` helper class which was _deprecated_ in the previous release has now been deleted + - It has been replaced by the improved `CommandResult` class ## 0.9.2 (June 28, 2018) -* Bug Fixes - * Fixed issue where piping and redirecting did not work correctly with paths that had spaces -* Enhancements - * Added ability to print a header above tab completion suggestions using `completion_header` member - * Added ``pager`` and ``pager_chop`` attributes to the ``cmd2.Cmd`` class - * ``pager`` defaults to **less -RXF** on POSIX and **more** on Windows - * ``pager_chop`` defaults to **less -SRXF** on POSIX and **more** on Windows - * Added ``chop`` argument to ``cmd2.Cmd.ppaged()`` method for displaying output using a pager - * If ``chop`` is ``False``, then ``self.pager`` is used as the pager - * Otherwise ``self.pager_chop`` is used as the pager - * Greatly improved the [table_display.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_display.py) example - * Now uses the new [tableformatter](https://github.com/python-tableformatter/tableformatter) module which looks better than ``tabulate`` -* Deprecations - * The ``CmdResult`` helper class is *deprecated* and replaced by the improved ``CommandResult`` class - * ``CommandResult`` has the following attributes: **stdout**, **stderr**, and **data** - * ``CmdResult`` had attributes of: **out**, **err**, **war** - * ``CmdResult`` will be deleted in the next release + +- Bug Fixes + - Fixed issue where piping and redirecting did not work correctly with paths that had spaces +- Enhancements + - Added ability to print a header above tab completion suggestions using `completion_header` member + - Added `pager` and `pager_chop` attributes to the `cmd2.Cmd` class + - `pager` defaults to **less -RXF** on POSIX and **more** on Windows + - `pager_chop` defaults to **less -SRXF** on POSIX and **more** on Windows + - Added `chop` argument to `cmd2.Cmd.ppaged()` method for displaying output using a pager + - If `chop` is `False`, then `self.pager` is used as the pager + - Otherwise `self.pager_chop` is used as the pager + - Greatly improved the [table_display.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_display.py) example + - Now uses the new [tableformatter](https://github.com/python-tableformatter/tableformatter) module which looks better than `tabulate` +- Deprecations + - The `CmdResult` helper class is _deprecated_ and replaced by the improved `CommandResult` class + - `CommandResult` has the following attributes: **stdout**, **stderr**, and **data** + - `CmdResult` had attributes of: **out**, **err**, **war** + - `CmdResult` will be deleted in the next release ## 0.8.8 (June 28, 2018) -* Bug Fixes - * Prevent crashes that could occur attempting to open a file in non-existent directory or with very long filename -* Enhancements - * `display_matches` is no longer restricted to delimited strings + +- Bug Fixes + - Prevent crashes that could occur attempting to open a file in non-existent directory or with very long filename +- Enhancements + - `display_matches` is no longer restricted to delimited strings ## 0.9.1 (May 28, 2018) -* Bug Fixes - * fix packaging error for 0.8.x versions (yes we had to deploy a new version + +- Bug Fixes + - fix packaging error for 0.8.x versions (yes we had to deploy a new version of the 0.9.x series to fix a packaging error with the 0.8.x version) ## 0.9.0 (May 28, 2018) -* Bug Fixes - * If self.default_to_shell is true, then redirection and piping are now properly passed to the shell. Previously it was truncated. - * Submenus now call all hooks, it used to just call precmd and postcmd. -* Enhancements - * Automatic completion of ``argparse`` arguments via ``cmd2.argparse_completer.AutoCompleter`` - * See the [tab_autocompletion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocompletion.py) example for a demonstration of how to use this feature - * ``cmd2`` no longer depends on the ``six`` module - * ``cmd2`` is now a multi-file Python package instead of a single-file module - * New pyscript approach that provides a pythonic interface to commands in the cmd2 application. - * Switch command parsing from pyparsing to custom code which utilizes shlex. - * The object passed to do_* methods has changed. It no longer is the pyparsing object, it's a new Statement object, which is a subclass of ``str``. The statement object has many attributes which give you access to various components of the parsed input. If you were using anything but the string in your do_* methods, this change will require you to update your code. - * ``commentGrammars`` is no longer supported or available. Comments are C-style or python style. - * Input redirection no longer supported. Use the load command instead. - * ``multilineCommand`` attribute is ``now multiline_command`` - * ``identchars`` is now ignored. The standardlibrary cmd uses those characters to split the first "word" of the input, but cmd2 hasn't used those for a while, and the new parsing logic parses on whitespace, which has the added benefit of full unicode support, unlike cmd or prior versions of cmd2. - * ``set_posix_shlex`` function and ``POSIX_SHLEX`` variable have been removed. Parsing behavior is now always the more forgiving ``posix=false``. - * ``set_strip_quotes`` function and ``STRIP_QUOTES_FOR_NON_POSIX`` have been removed. Quotes are stripped from arguments when presented as a list (a la ``sys.argv``), and present when arguments are presented as a string (like the string passed to do_*). -* Changes - * ``strip_ansi()`` and ``strip_quotes()`` functions have moved to new utils module - * Several constants moved to new constants module - * Submenu support has been moved to a new [cmd2-submenu](https://github.com/python-cmd2/cmd2-submenu) plugin. If you use submenus, you will need to update your dependencies and modify your imports. -* Deletions (potentially breaking changes) - * Deleted all ``optparse`` code which had previously been deprecated in release 0.8.0 - * The ``options`` decorator no longer exists - * All ``cmd2`` code should be ported to use the new ``argparse``-based decorators - * See the [Argument Processing](http://cmd2.readthedocs.io/en/latest/argument_processing.html) section of the documentation for more information on these decorators - * Alternatively, see the [argparse_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_example.py) - * Deleted ``cmd_with_subs_completer``, ``get_subcommands``, and ``get_subcommand_completer`` - * Replaced by default AutoCompleter implementation for all commands using argparse - * Deleted support for old method of calling application commands with ``cmd()`` and ``self`` - * ``cmd2.redirector`` is no longer supported. Output redirection can only be done with '>' or '>>' - * Deleted ``postparse()`` hook since it was redundant with ``postparsing_precmd`` -* Python 2 no longer supported - * ``cmd2`` now supports Python 3.4+ -* Known Issues - * Some developers have noted very slow performance when importing the ``cmd2`` module. The issue - it intermittent, and investigation of the root cause is ongoing. + +- Bug Fixes + - If self.default_to_shell is true, then redirection and piping are now properly passed to the shell. Previously it was truncated. + - Submenus now call all hooks, it used to just call precmd and postcmd. +- Enhancements + - Automatic completion of `argparse` arguments via `cmd2.argparse_completer.AutoCompleter` + - See the [tab_autocompletion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_autocompletion.py) example for a demonstration of how to use this feature + - `cmd2` no longer depends on the `six` module + - `cmd2` is now a multi-file Python package instead of a single-file module + - New pyscript approach that provides a pythonic interface to commands in the cmd2 application. + - Switch command parsing from pyparsing to custom code which utilizes shlex. + - The object passed to do*\* methods has changed. It no longer is the pyparsing object, it's a new Statement object, which is a subclass of `str`. The statement object has many attributes which give you access to various components of the parsed input. If you were using anything but the string in your do*\* methods, this change will require you to update your code. + - `commentGrammars` is no longer supported or available. Comments are C-style or python style. + - Input redirection no longer supported. Use the load command instead. + - `multilineCommand` attribute is `now multiline_command` + - `identchars` is now ignored. The standardlibrary cmd uses those characters to split the first "word" of the input, but cmd2 hasn't used those for a while, and the new parsing logic parses on whitespace, which has the added benefit of full unicode support, unlike cmd or prior versions of cmd2. + - `set_posix_shlex` function and `POSIX_SHLEX` variable have been removed. Parsing behavior is now always the more forgiving `posix=false`. + - `set_strip_quotes` function and `STRIP_QUOTES_FOR_NON_POSIX` have been removed. Quotes are stripped from arguments when presented as a list (a la `sys.argv`), and present when arguments are presented as a string (like the string passed to do\_\*). +- Changes + - `strip_ansi()` and `strip_quotes()` functions have moved to new utils module + - Several constants moved to new constants module + - Submenu support has been moved to a new [cmd2-submenu](https://github.com/python-cmd2/cmd2-submenu) plugin. If you use submenus, you will need to update your dependencies and modify your imports. +- Deletions (potentially breaking changes) + - Deleted all `optparse` code which had previously been deprecated in release 0.8.0 + - The `options` decorator no longer exists + - All `cmd2` code should be ported to use the new `argparse`-based decorators + - See the [Argument Processing](http://cmd2.readthedocs.io/en/latest/argument_processing.html) section of the documentation for more information on these decorators + - Alternatively, see the [argparse_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_example.py) + - Deleted `cmd_with_subs_completer`, `get_subcommands`, and `get_subcommand_completer` + - Replaced by default AutoCompleter implementation for all commands using argparse + - Deleted support for old method of calling application commands with `cmd()` and `self` + - `cmd2.redirector` is no longer supported. Output redirection can only be done with '>' or '>>' + - Deleted `postparse()` hook since it was redundant with `postparsing_precmd` +- Python 2 no longer supported + - `cmd2` now supports Python 3.4+ +- Known Issues + - Some developers have noted very slow performance when importing the `cmd2` module. The issue + it intermittent, and investigation of the root cause is ongoing. ## 0.8.6 (May 27, 2018) -* Bug Fixes - * Commands using the @with_argparser_and_unknown_args were not correctly recognized when tab completing - * Fixed issue where completion display function was overwritten when a submenu quits - * Fixed ``AttributeError`` on Windows when running a ``select`` command cause by **pyreadline** not implementing ``remove_history_item`` -* Enhancements - * Added warning about **libedit** variant of **readline** not being supported on macOS - * Added tab completion of alias names in value field of **alias** command - * Enhanced the ``py`` console in the following ways - * Added tab completion of Python identifiers instead of **cmd2** commands - * Separated the ``py`` console history from the **cmd2** history + +- Bug Fixes + - Commands using the @with_argparser_and_unknown_args were not correctly recognized when tab completing + - Fixed issue where completion display function was overwritten when a submenu quits + - Fixed `AttributeError` on Windows when running a `select` command cause by **pyreadline** not implementing `remove_history_item` +- Enhancements + - Added warning about **libedit** variant of **readline** not being supported on macOS + - Added tab completion of alias names in value field of **alias** command + - Enhanced the `py` console in the following ways + - Added tab completion of Python identifiers instead of **cmd2** commands + - Separated the `py` console history from the **cmd2** history ## 0.8.5 (April 15, 2018) -* Bug Fixes - * Fixed a bug with all argument decorators where the wrapped function wasn't returning a value and thus couldn't cause the cmd2 app to quit - -* Enhancements - * Added support for verbose help with -v where it lists a brief summary of what each command does - * Added support for categorizing commands into groups within the help menu - * See the [Grouping Commands](http://cmd2.readthedocs.io/en/latest/argument_processing.html?highlight=verbose#grouping-commands) section of the docs for more info - * See [help_categories.py](https://github.com/python-cmd2/cmd2/blob/master/examples/help_categories.py) for an example - * Tab completion of paths now supports ~user user path expansion - * Simplified implementation of various tab completion functions so they no longer require ``ctypes`` - * Expanded documentation of ``display_matches`` list to clarify its purpose. See cmd2.py for this documentation. - * Adding opening quote to tab completion if any of the completion suggestions have a space. - -* **Python 2 EOL notice** - * This is the last release where new features will be added to ``cmd2`` for Python 2.7 - * The 0.9.0 release of ``cmd2`` will support Python 3.4+ only - * Additional 0.8.x releases may be created to supply bug fixes for Python 2.7 up until August 31, 2018 - * After August 31, 2018 not even bug fixes will be provided for Python 2.7 + +- Bug Fixes + + - Fixed a bug with all argument decorators where the wrapped function wasn't returning a value and thus couldn't cause the cmd2 app to quit + +- Enhancements + + - Added support for verbose help with -v where it lists a brief summary of what each command does + - Added support for categorizing commands into groups within the help menu + - See the [Grouping Commands](http://cmd2.readthedocs.io/en/latest/argument_processing.html?highlight=verbose#grouping-commands) section of the docs for more info + - See [help_categories.py](https://github.com/python-cmd2/cmd2/blob/master/examples/help_categories.py) for an example + - Tab completion of paths now supports ~user user path expansion + - Simplified implementation of various tab completion functions so they no longer require `ctypes` + - Expanded documentation of `display_matches` list to clarify its purpose. See cmd2.py for this documentation. + - Adding opening quote to tab completion if any of the completion suggestions have a space. + +- **Python 2 EOL notice** + - This is the last release where new features will be added to `cmd2` for Python 2.7 + - The 0.9.0 release of `cmd2` will support Python 3.4+ only + - Additional 0.8.x releases may be created to supply bug fixes for Python 2.7 up until August 31, 2018 + - After August 31, 2018 not even bug fixes will be provided for Python 2.7 ## 0.8.4 (April 10, 2018) -* Bug Fixes - * Fixed conditional dependency issue in setup.py that was in 0.8.3. + +- Bug Fixes + - Fixed conditional dependency issue in setup.py that was in 0.8.3. ## 0.8.3 (April 09, 2018) -* Bug Fixes - * Fixed ``help`` command not calling functions for help topics - * Fixed not being able to use quoted paths when redirecting with ``<`` and ``>`` - -* Enhancements - * Tab completion has been overhauled and now supports completion of strings with quotes and spaces. - * Tab completion will automatically add an opening quote if a string with a space is completed. - * Added ``delimiter_complete`` function for tab completing delimited strings - * Added more control over tab completion behavior including the following flags. The use of these flags is documented in cmd2.py - * ``allow_appended_space`` - * ``allow_closing_quote`` - * Due to the tab completion changes, non-Windows platforms now depend on [wcwidth](https://pypi.python.org/pypi/wcwidth). - * An alias name can now match a command name. - * An alias can now resolve to another alias. - -* Attribute Changes (Breaks backward compatibility) - * ``exclude_from_help`` is now called ``hidden_commands`` since these commands are hidden from things other than help, including tab completion - * This list also no longer takes the function names of commands (``do_history``), but instead uses the command names themselves (``history``) - * ``excludeFromHistory`` is now called ``exclude_from_history`` - * ``cmd_with_subs_completer()`` no longer takes an argument called ``base``. Adding tab completion to subcommands has been simplified to declaring it in the - subcommand parser's default settings. This easily allows arbitrary completers like path_complete to be used. - See [subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py) for an example of how to use - tab completion in subcommands. In addition, the docstring for ``cmd_with_subs_completer()`` offers more details. +- Bug Fixes + + - Fixed `help` command not calling functions for help topics + - Fixed not being able to use quoted paths when redirecting with `<` and `>` + +- Enhancements + + - Tab completion has been overhauled and now supports completion of strings with quotes and spaces. + - Tab completion will automatically add an opening quote if a string with a space is completed. + - Added `delimiter_complete` function for tab completing delimited strings + - Added more control over tab completion behavior including the following flags. The use of these flags is documented in cmd2.py + - `allow_appended_space` + - `allow_closing_quote` + - Due to the tab completion changes, non-Windows platforms now depend on [wcwidth](https://pypi.python.org/pypi/wcwidth). + - An alias name can now match a command name. + - An alias can now resolve to another alias. + +- Attribute Changes (Breaks backward compatibility) + - `exclude_from_help` is now called `hidden_commands` since these commands are hidden from things other than help, including tab completion + - This list also no longer takes the function names of commands (`do_history`), but instead uses the command names themselves (`history`) + - `excludeFromHistory` is now called `exclude_from_history` + - `cmd_with_subs_completer()` no longer takes an argument called `base`. Adding tab completion to subcommands has been simplified to declaring it in the + subcommand parser's default settings. This easily allows arbitrary completers like path_complete to be used. + See [subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py) for an example of how to use + tab completion in subcommands. In addition, the docstring for `cmd_with_subs_completer()` offers more details. ## 0.8.2 (March 21, 2018) -* Bug Fixes - * Fixed a bug in tab completion of command names within sub-menus - * Fixed a bug when using persistent readline history in Python 2.7 - * Fixed a bug where the ``AddSubmenu`` decorator didn't work with a default value for ``shared_attributes`` - * Added a check to ``ppaged()`` to only use a pager when running in a real fully functional terminal -* Enhancements - * Added [quit_on_sigint](http://cmd2.readthedocs.io/en/latest/settingchanges.html#quit-on-sigint) attribute to enable canceling current line instead of quitting when Ctrl+C is typed - * Added possibility of having readline history preservation in a SubMenu - * Added [table_display.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_display.py) example to demonstrate how to display tabular data - * Added command aliasing with ``alias`` and ``unalias`` commands - * Added the ability to load an initialization script at startup - * See [alias_startup.py](https://github.com/python-cmd2/cmd2/blob/master/examples/alias_startup.py) for an example - * Added a default SIGINT handler which terminates any open pipe subprocesses and re-raises a KeyboardInterrupt - * For macOS, will load the ``gnureadline`` module if available and ``readline`` if not +- Bug Fixes + - Fixed a bug in tab completion of command names within sub-menus + - Fixed a bug when using persistent readline history in Python 2.7 + - Fixed a bug where the `AddSubmenu` decorator didn't work with a default value for `shared_attributes` + - Added a check to `ppaged()` to only use a pager when running in a real fully functional terminal +- Enhancements + - Added [quit_on_sigint](http://cmd2.readthedocs.io/en/latest/settingchanges.html#quit-on-sigint) attribute to enable canceling current line instead of quitting when Ctrl+C is typed + - Added possibility of having readline history preservation in a SubMenu + - Added [table_display.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_display.py) example to demonstrate how to display tabular data + - Added command aliasing with `alias` and `unalias` commands + - Added the ability to load an initialization script at startup + - See [alias_startup.py](https://github.com/python-cmd2/cmd2/blob/master/examples/alias_startup.py) for an example + - Added a default SIGINT handler which terminates any open pipe subprocesses and re-raises a KeyboardInterrupt + - For macOS, will load the `gnureadline` module if available and `readline` if not ## 0.8.1 (March 9, 2018) -* Bug Fixes - * Fixed a bug if a non-existent **do_*** method was added to the ``exclude_from_help`` list - * Fixed a bug in a unit test which would fail if your home directory was empty on a Linux system - * Fixed outdated help text for the **edit** command - * Fixed outdated [remove_unused.py](https://github.com/python-cmd2/cmd2/blob/master/examples/remove_unused.py) -* Enhancements - * Added support for sub-menus. - * See [submenus.py](https://github.com/python-cmd2/cmd2/blob/master/examples/submenus.py) for an example of how to use it - * Added option for persistent readline history - * See [persistent_history.py](https://github.com/python-cmd2/cmd2/blob/master/examples/persistent_history.py) for an example - * See the [Searchable command history](http://cmd2.readthedocs.io/en/latest/freefeatures.html#searchable-command-history) section of the documentation for more info - * Improved PyPI packaging by including unit tests and examples in the tarball - * Improved documentation to make it more obvious that **poutput()** should be used instead of **print()** - * ``exclude_from_help`` and ``excludeFromHistory`` are now instance instead of class attributes - * Added flag and index based tab completion helper functions - * See [tab_completion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_completion.py) - * Added support for displaying output which won't fit on the screen via a pager using ``ppaged()`` - * See [paged_output.py](https://github.com/python-cmd2/cmd2/blob/master/examples/paged_output.py) -* Attributes Removed (**can cause breaking changes**) - * ``abbrev`` - Removed support for abbreviated commands - * Good tab completion makes this unnecessary and its presence could cause harmful unintended actions - * ``case_insensitive`` - Removed support for case-insensitive command parsing - * Its presence wasn't very helpful and could cause harmful unintended actions +- Bug Fixes + - Fixed a bug if a non-existent **do\_\*** method was added to the `exclude_from_help` list + - Fixed a bug in a unit test which would fail if your home directory was empty on a Linux system + - Fixed outdated help text for the **edit** command + - Fixed outdated [remove_unused.py](https://github.com/python-cmd2/cmd2/blob/master/examples/remove_unused.py) +- Enhancements + - Added support for sub-menus. + - See [submenus.py](https://github.com/python-cmd2/cmd2/blob/master/examples/submenus.py) for an example of how to use it + - Added option for persistent readline history + - See [persistent_history.py](https://github.com/python-cmd2/cmd2/blob/master/examples/persistent_history.py) for an example + - See the [Searchable command history](http://cmd2.readthedocs.io/en/latest/freefeatures.html#searchable-command-history) section of the documentation for more info + - Improved PyPI packaging by including unit tests and examples in the tarball + - Improved documentation to make it more obvious that **poutput()** should be used instead of **print()** + - `exclude_from_help` and `excludeFromHistory` are now instance instead of class attributes + - Added flag and index based tab completion helper functions + - See [tab_completion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/tab_completion.py) + - Added support for displaying output which won't fit on the screen via a pager using `ppaged()` + - See [paged_output.py](https://github.com/python-cmd2/cmd2/blob/master/examples/paged_output.py) +- Attributes Removed (**can cause breaking changes**) + - `abbrev` - Removed support for abbreviated commands + - Good tab completion makes this unnecessary and its presence could cause harmful unintended actions + - `case_insensitive` - Removed support for case-insensitive command parsing + - Its presence wasn't very helpful and could cause harmful unintended actions ## 0.8.0 (February 1, 2018) -* Bug Fixes - * Fixed unit tests on Python 3.7 due to changes in how re.escape() behaves in Python 3.7 - * Fixed a bug where unknown commands were getting saved in the history -* Enhancements - * Three new decorators for **do_*** commands to make argument parsing easier - * **with_argument_list** decorator to change argument type from str to List[str] - * **do_*** commands get a single argument which is a list of strings, as pre-parsed by shlex.split() - * **with_arparser** decorator for strict argparse-based argument parsing of command arguments - * **do_*** commands get a single argument which is the output of argparse.parse_args() - * **with_argparser_and_unknown_args** decorator for argparse-based argument parsing, but allows unknown args - * **do_*** commands get two arguments, the output of argparse.parse_known_args() - * See the [Argument Processing](http://cmd2.readthedocs.io/en/latest/argument_processing.html) section of the documentation for more information on these decorators - * Alternatively, see the [argparse_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_example.py) - and [arg_print.py](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_print.py) examples - * Added support for Argparse subcommands when using the **with_argument_parser** or **with_argparser_and_unknown_args** decorators - * See [subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py) for an example of how to use subcommands - * Tab completion of subcommand names is automatically supported - * The **__relative_load** command is now hidden from the help menu by default - * This command is not intended to be called from the command line, only from within scripts - * The **set** command now has an additional **-a/--all** option to also display read-only settings - * The **history** command can now run, edit, and save prior commands, in addition to displaying prior commands. - * The **history** command can now automatically generate a transcript file for regression testing - * This makes creating regression tests for your ``cmd2`` application trivial -* Commands Removed - * The **cmdenvironment** has been removed and its functionality incorporated into the **-a/--all** argument to **set** - * The **show** command has been removed. Its functionality has always existing within **set** and continues to do so - * The **save** command has been removed. The capability to save commands is now part of the **history** command. - * The **run** command has been removed. The capability to run prior commands is now part of the **history** command. -* Other changes - * The **edit** command no longer allows you to edit prior commands. The capability to edit prior commands is now part of the **history** command. The **edit** command still allows you to edit arbitrary files. - * the **autorun_on_edit** setting has been removed. - * For Python 3.4 and earlier, ``cmd2`` now has an additional dependency on the ``contextlib2`` module -* Deprecations - * The old **options** decorator for optparse-based argument parsing is now *deprecated* - * The old decorator is still present for now, but will be removed in a future release - * ``cmd2`` no longer includes **optparse.make_option**, so if your app needs it import directly from optparse + +- Bug Fixes + - Fixed unit tests on Python 3.7 due to changes in how re.escape() behaves in Python 3.7 + - Fixed a bug where unknown commands were getting saved in the history +- Enhancements + - Three new decorators for **do\_\*** commands to make argument parsing easier + - **with_argument_list** decorator to change argument type from str to List[str] + - **do\_\*** commands get a single argument which is a list of strings, as pre-parsed by shlex.split() + - **with_arparser** decorator for strict argparse-based argument parsing of command arguments + - **do\_\*** commands get a single argument which is the output of argparse.parse_args() + - **with_argparser_and_unknown_args** decorator for argparse-based argument parsing, but allows unknown args + - **do\_\*** commands get two arguments, the output of argparse.parse_known_args() + - See the [Argument Processing](http://cmd2.readthedocs.io/en/latest/argument_processing.html) section of the documentation for more information on these decorators + - Alternatively, see the [argparse_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_example.py) + and [arg_print.py](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_print.py) examples + - Added support for Argparse subcommands when using the **with_argument_parser** or **with_argparser_and_unknown_args** decorators + - See [subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py) for an example of how to use subcommands + - Tab completion of subcommand names is automatically supported + - The **\_\_relative_load** command is now hidden from the help menu by default + - This command is not intended to be called from the command line, only from within scripts + - The **set** command now has an additional **-a/--all** option to also display read-only settings + - The **history** command can now run, edit, and save prior commands, in addition to displaying prior commands. + - The **history** command can now automatically generate a transcript file for regression testing + - This makes creating regression tests for your `cmd2` application trivial +- Commands Removed + - The **cmdenvironment** has been removed and its functionality incorporated into the **-a/--all** argument to **set** + - The **show** command has been removed. Its functionality has always existing within **set** and continues to do so + - The **save** command has been removed. The capability to save commands is now part of the **history** command. + - The **run** command has been removed. The capability to run prior commands is now part of the **history** command. +- Other changes + - The **edit** command no longer allows you to edit prior commands. The capability to edit prior commands is now part of the **history** command. The **edit** command still allows you to edit arbitrary files. + - the **autorun_on_edit** setting has been removed. + - For Python 3.4 and earlier, `cmd2` now has an additional dependency on the `contextlib2` module +- Deprecations + - The old **options** decorator for optparse-based argument parsing is now _deprecated_ + - The old decorator is still present for now, but will be removed in a future release + - `cmd2` no longer includes **optparse.make_option**, so if your app needs it import directly from optparse ## 0.7.9 (January 4, 2018) -* Bug Fixes - * Fixed a couple broken examples -* Enhancements - * Improved documentation for modifying shortcuts (command aliases) - * Made ``pyreadline`` a dependency on Windows to ensure tab completion works -* Other changes - * Abandoned official support for Python 3.3. It should still work, just don't have an easy way to test it anymore. +- Bug Fixes + - Fixed a couple broken examples +- Enhancements + - Improved documentation for modifying shortcuts (command aliases) + - Made `pyreadline` a dependency on Windows to ensure tab completion works +- Other changes + - Abandoned official support for Python 3.3. It should still work, just don't have an easy way to test it anymore. ## 0.7.8 (November 8, 2017) -* Bug Fixes - * Fixed ``poutput()`` so it can print an integer zero and other **falsy** things - * Fixed a bug which was causing autodoc to fail for building docs on Readthedocs - * Fixed bug due to ``pyperclip`` dependency radically changing its project structure in latest version -* Enhancements - * Improved documentation for user-settable environment parameters - * Improved documentation for overriding the default supported comment styles - * Added ``runcmds_plus_hooks()`` method to run multiple commands w/o a cmdloop +- Bug Fixes + - Fixed `poutput()` so it can print an integer zero and other **falsy** things + - Fixed a bug which was causing autodoc to fail for building docs on Readthedocs + - Fixed bug due to `pyperclip` dependency radically changing its project structure in latest version +- Enhancements + - Improved documentation for user-settable environment parameters + - Improved documentation for overriding the default supported comment styles + - Added `runcmds_plus_hooks()` method to run multiple commands w/o a cmdloop ## 0.7.7 (August 25, 2017) -* Bug Fixes - * Added workaround for bug which occurs in Python 2.7 on Linux when ``pygtk`` is installed - * ``pfeedback()`` now honors feedback_to_output setting and won't redirect when it is ``False`` - * For ``edit`` command, both **editor** and **filename** can now have spaces in the name/path - * Fixed a bug which occurred when stdin was a pipe instead of a tty due to input redirection -* Enhancements - * ``feedback_to_output`` now defaults to ``False`` so info like command timing won't redirect - * Transcript regular expressions now have predictable, tested, and documented behavior - * This makes a breaking change to the format and expectations of transcript testing - * The prior behavior removed whitespace before making the comparison, now whitespace must match exactly - * Prior version did not allow regexes with whitespace, new version allows any regex - * Improved display for ``load`` command and input redirection when **echo** is ``True`` +- Bug Fixes + - Added workaround for bug which occurs in Python 2.7 on Linux when `pygtk` is installed + - `pfeedback()` now honors feedback_to_output setting and won't redirect when it is `False` + - For `edit` command, both **editor** and **filename** can now have spaces in the name/path + - Fixed a bug which occurred when stdin was a pipe instead of a tty due to input redirection +- Enhancements + - `feedback_to_output` now defaults to `False` so info like command timing won't redirect + - Transcript regular expressions now have predictable, tested, and documented behavior + - This makes a breaking change to the format and expectations of transcript testing + - The prior behavior removed whitespace before making the comparison, now whitespace must match exactly + - Prior version did not allow regexes with whitespace, new version allows any regex + - Improved display for `load` command and input redirection when **echo** is `True` ## 0.7.6 (August 11, 2017) -* Bug Fixes - * Case-sensitive command parsing was completely broken and has been fixed - * ``+d`` now properly quits when case-sensitive command parsing is enabled - * Fixed some pyperclip clipboard interaction bugs on Linux - * Fixed some timing bugs when running unit tests in parallel by using monkeypatch -* Enhancements - * Enhanced tab completion of cmd2 command names to support case-insensitive completion - * Added an example showing how to remove unused commands - * Improved how transcript testing handles prompts with ANSI escape codes by stripping them - * Greatly improved implementation for how command output gets piped to a shell command +- Bug Fixes + - Case-sensitive command parsing was completely broken and has been fixed + - `+d` now properly quits when case-sensitive command parsing is enabled + - Fixed some pyperclip clipboard interaction bugs on Linux + - Fixed some timing bugs when running unit tests in parallel by using monkeypatch +- Enhancements + - Enhanced tab completion of cmd2 command names to support case-insensitive completion + - Added an example showing how to remove unused commands + - Improved how transcript testing handles prompts with ANSI escape codes by stripping them + - Greatly improved implementation for how command output gets piped to a shell command ## 0.7.5 (July 8, 2017) -* Bug Fixes - * `case_insensitive` is no longer a runtime-settable parameter, but it was still listed as such - * Fixed a recursive loop bug when abbreviated commands are enabled and it could get stuck in the editor forever - * Added additional command abbreviations to the "exclude from history" list - * Fixed argparse_example.py and pirate.py examples and transcript_regex.txt transcript - * Fixed a bug in a unit test which occurred under unusual circumstances -* Enhancements - * Organized all attributes used to configure the ParserManager into a single location - * Set the default value of `abbrev` to `False` (which controls whether or not abbreviated commands are allowed) - * With good tab completion of command names, using abbreviated commands isn't particularly useful - * And it can create complications if you are't careful - * Improved implementation of `load` to use command queue instead of nested inner loop +- Bug Fixes + - `case_insensitive` is no longer a runtime-settable parameter, but it was still listed as such + - Fixed a recursive loop bug when abbreviated commands are enabled and it could get stuck in the editor forever + - Added additional command abbreviations to the "exclude from history" list + - Fixed argparse_example.py and pirate.py examples and transcript_regex.txt transcript + - Fixed a bug in a unit test which occurred under unusual circumstances +- Enhancements + - Organized all attributes used to configure the ParserManager into a single location + - Set the default value of `abbrev` to `False` (which controls whether or not abbreviated commands are allowed) + - With good tab completion of command names, using abbreviated commands isn't particularly useful + - And it can create complications if you are't careful + - Improved implementation of `load` to use command queue instead of nested inner loop ## 0.7.4 (July 3, 2017) -* Bug fixes - * Fixed a couple bugs in interacting with pastebuffer/clipboard on macOS and Linux - * Fixed a couple bugs in edit and save commands if called when history is empty - * Ability to pipe ``cmd2`` command output to a shell command is now more reliable, particularly on Windows - * Fixed a bug in ``pyscript`` command on Windows related to ``\`` being interpreted as an escape -* Enhancements - * Ensure that path and shell command tab completion results are alphabetically sorted - * Removed feature for load command to load scripts from URLS - * It didn't work, there were no unit tests, and it felt out of place - * Removed presence of a default file name and default file extension - * These also strongly felt out of place - * ``load`` and ``_relative_load`` now require a file path - * ``edit`` and ``save`` now use a temporary file if a file path isn't provided - * ``load`` command has better error checking and reporting - * Clipboard copy and paste functionality is now handled by the **pyperclip** module - * ``shell`` command now supports redirection and piping of output - * Added a lot of unit tests -* Other changes - * Removed pause command - * Added a dependency on the **pyperclip** module +- Bug fixes + - Fixed a couple bugs in interacting with pastebuffer/clipboard on macOS and Linux + - Fixed a couple bugs in edit and save commands if called when history is empty + - Ability to pipe `cmd2` command output to a shell command is now more reliable, particularly on Windows + - Fixed a bug in `pyscript` command on Windows related to `\` being interpreted as an escape +- Enhancements + - Ensure that path and shell command tab completion results are alphabetically sorted + - Removed feature for load command to load scripts from URLS + - It didn't work, there were no unit tests, and it felt out of place + - Removed presence of a default file name and default file extension + - These also strongly felt out of place + - `load` and `_relative_load` now require a file path + - `edit` and `save` now use a temporary file if a file path isn't provided + - `load` command has better error checking and reporting + - Clipboard copy and paste functionality is now handled by the **pyperclip** module + - `shell` command now supports redirection and piping of output + - Added a lot of unit tests +- Other changes + - Removed pause command + - Added a dependency on the **pyperclip** module ## 0.7.3 (June 23, 2017) -* Bug fixes - * Fixed a bug in displaying a span of history items when only an end index is supplied - * Fixed a bug which caused transcript test failures to display twice -* Enhancements - * Added the ability to exclude commands from the help menu (**eof** included by default) - * Redundant **list** command removed and features merged into **history** command - * Added **pyscript** command which supports tab completion and running Python scripts with arguments - * Improved tab completion of file system paths, command names, and shell commands - * Thanks to Kevin Van Brunt for all of the help with debugging and testing this - * Changed default value of USE_ARG_LIST to True - this affects the beavhior of all **@options** commands - * **WARNING**: This breaks backwards compatibility, to restore backwards compatibility, add this to the - **__init__()** method in your custom class derived from cmd2.Cmd: - * cmd2.set_use_arg_list(False) - * This change improves argument parsing for all new applications - * Refactored code to encapsulate most of the pyparsing logic into a ParserManager class +- Bug fixes + - Fixed a bug in displaying a span of history items when only an end index is supplied + - Fixed a bug which caused transcript test failures to display twice +- Enhancements + - Added the ability to exclude commands from the help menu (**eof** included by default) + - Redundant **list** command removed and features merged into **history** command + - Added **pyscript** command which supports tab completion and running Python scripts with arguments + - Improved tab completion of file system paths, command names, and shell commands + - Thanks to Kevin Van Brunt for all of the help with debugging and testing this + - Changed default value of USE_ARG_LIST to True - this affects the beavhior of all **@options** commands + - **WARNING**: This breaks backwards compatibility, to restore backwards compatibility, add this to the \***\*init**()\*\* method in your custom class derived from cmd2.Cmd: + - cmd2.set_use_arg_list(False) + - This change improves argument parsing for all new applications + - Refactored code to encapsulate most of the pyparsing logic into a ParserManager class ## 0.7.2 (May 22, 2017) -* Added a MANIFEST.ini file to make sure a few extra files get included in the PyPI source distribution +- Added a MANIFEST.ini file to make sure a few extra files get included in the PyPI source distribution ## 0.7.1 (May 22, 2017) -* Bug fixes - * ``-`` wasn't being treated as a legal character - * The allow_cli_args attribute wasn't properly disabling parsing of args at invocation when False - * py command wasn't allowing scripts which used *cmd* function prior to entering an interactive Python session - * Don't throw exception when piping output to a shell command - * Transcript testing now properly calls ``preloop`` before and ``postloop`` after - * Fixed readline bug related to ANSI color escape codes in the prompt -* Added CONTRIBUTING.md and CODE_OF_CONDUCT.md files -* Added unicode parsing unit tests and listed unicode support as a feature when using Python 3 -* Added more examples and improved documentation - * Example for how use cmd2 in a way where it doesn't own the main loop so it can integrate with external event loops - * Example for how to use argparse for parsing command-line args at invocation - * Example for how to use the **py** command to run Python scripts which use conditional control flow - * Example of how to use regular expressions in a transcript test -* Added CmdResult namedtumple for returning and storing results -* Added local file system path completion for ``edit``, ``load``, ``save``, and ``shell`` commands -* Add shell command completion for ``shell`` command or ``!`` shortcut -* Abbreviated multiline commands are no longer allowed (they never worked correctly anyways) +- Bug fixes + - `-` wasn't being treated as a legal character + - The allow_cli_args attribute wasn't properly disabling parsing of args at invocation when False + - py command wasn't allowing scripts which used _cmd_ function prior to entering an interactive Python session + - Don't throw exception when piping output to a shell command + - Transcript testing now properly calls `preloop` before and `postloop` after + - Fixed readline bug related to ANSI color escape codes in the prompt +- Added CONTRIBUTING.md and CODE_OF_CONDUCT.md files +- Added unicode parsing unit tests and listed unicode support as a feature when using Python 3 +- Added more examples and improved documentation + - Example for how use cmd2 in a way where it doesn't own the main loop so it can integrate with external event loops + - Example for how to use argparse for parsing command-line args at invocation + - Example for how to use the **py** command to run Python scripts which use conditional control flow + - Example of how to use regular expressions in a transcript test +- Added CmdResult namedtumple for returning and storing results +- Added local file system path completion for `edit`, `load`, `save`, and `shell` commands +- Add shell command completion for `shell` command or `!` shortcut +- Abbreviated multiline commands are no longer allowed (they never worked correctly anyways) ## 0.7.0 (February 23, 2017) -* Refactored to use six module for a unified codebase which supports both Python 2 and Python 3 -* Stabilized on all platforms (Windows, Mac, Linux) and all supported Python versions (2.7, 3.3, 3.4, 3.5, 3.6, PyPy) -* Added lots of unit tests and fixed a number of bugs -* Improved documentation and moved it to cmd2.readthedocs.io - +- Refactored to use six module for a unified codebase which supports both Python 2 and Python 3 +- Stabilized on all platforms (Windows, Mac, Linux) and all supported Python versions (2.7, 3.3, 3.4, 3.5, 3.6, PyPy) +- Added lots of unit tests and fixed a number of bugs +- Improved documentation and moved it to cmd2.readthedocs.io ## 0.6.9 (October 3, 2016) -* Support Python 3 input() -* Fix subprocess.mswindows bug -* Add Python3.6 support -* Drop distutils from setup.py - +- Support Python 3 input() +- Fix subprocess.mswindows bug +- Add Python3.6 support +- Drop distutils from setup.py ## 0.6.8 (December 9, 2014) -* better editor checking (by Ian Cordascu) - +- better editor checking (by Ian Cordascu) ## 0.6.6.1 (August 14, 2013) -* No changes to code trunk. Generated sdist from Python 2.7 to avoid 2to3 changes being applied to source. (Issue https://bitbucket.org/catherinedevlin/cmd2/issue/6/packaging-bug) - +- No changes to code trunk. Generated sdist from Python 2.7 to avoid 2to3 changes being applied to source. (Issue https://bitbucket.org/catherinedevlin/cmd2/issue/6/packaging-bug) ## 0.6.6 (August 6, 2013) -* Added fix by bitbucket.org/desaintmartin to silence the editor check. bitbucket.org/catherinedevlin/cmd2/issue/1/silent-editor-check - +- Added fix by bitbucket.org/desaintmartin to silence the editor check. bitbucket.org/catherinedevlin/cmd2/issue/1/silent-editor-check ## 0.6.5.1 (March 18, 2013) -* Bugfix for setup.py version check for Python 2.6, contributed by Tomaz Muraus (https://bitbucket.org/kami) - +- Bugfix for setup.py version check for Python 2.6, contributed by Tomaz Muraus (https://bitbucket.org/kami) ## 0.6.5 (February 29, 2013) -* Belatedly began a NEWS.txt -* Changed pyparsing requirement for compatibility with Python version (2 vs 3) +- Belatedly began a NEWS.txt +- Changed pyparsing requirement for compatibility with Python version (2 vs 3) diff --git a/README.md b/README.md index d9cde728..9a7def90 100755 --- a/README.md +++ b/README.md @@ -89,13 +89,16 @@ The best way to learn the cmd2 api is to delve into the example applications loc ## Tutorials - PyOhio 2019 presentation: - - [video](https://www.youtube.com/watch?v=pebeWrTqIIw) - - [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf) - - [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples) + - [video](https://www.youtube.com/watch?v=pebeWrTqIIw) + - [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf) + - [example code](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples) - [Cookiecutter](https://github.com/cookiecutter/cookiecutter) Templates from community - - Basic cookiecutter template for cmd2 application : https://github.com/jayrod/cookiecutter-python-cmd2 - - Advanced cookiecutter template with external plugin support : https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug -- [Example Applications](https://github.com/jayrod/cmd2-example-apps) + - Basic cookiecutter template for cmd2 application : https://github.com/jayrod/cookiecutter-python-cmd2 + - Advanced cookiecutter template with external plugin support : https://github.com/jayrod/cookiecutter-python-cmd2-ext-plug +- [cmd2 example applications](https://github.com/python-cmd2/cmd2/tree/master/examples) + - Basic cmd2 examples to demonstrate how to use various features +- [Advanced Examples](https://github.com/jayrod/cmd2-example-apps) + - More complex examples that demonstrate more featuers about how to put together a complete application ## Hello World diff --git a/cmd2/argparse_custom.py b/cmd2/argparse_custom.py index deba1df2..26cf5e85 100644 --- a/cmd2/argparse_custom.py +++ b/cmd2/argparse_custom.py @@ -485,12 +485,11 @@ def _action_set_choices_callable(self: argparse.Action, choices_callable: Choice """ # Verify consistent use of parameters if self.choices is not None: - err_msg = "None of the following parameters can be used alongside a choices parameter:\n" "choices_provider, completer" + err_msg = "None of the following parameters can be used alongside a choices parameter:\nchoices_provider, completer" raise (TypeError(err_msg)) elif self.nargs == 0: err_msg = ( - "None of the following parameters can be used on an action that takes no arguments:\n" - "choices_provider, completer" + "None of the following parameters can be used on an action that takes no arguments:\nchoices_provider, completer" ) raise (TypeError(err_msg)) @@ -774,7 +773,7 @@ def _add_argument_wrapper( num_params_set = len(choices_callables) - choices_callables.count(None) if num_params_set > 1: - err_msg = "Only one of the following parameters may be used at a time:\n" "choices_provider, completer" + err_msg = "Only one of the following parameters may be used at a time:\nchoices_provider, completer" raise (ValueError(err_msg)) # Pre-process special ranged nargs diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py index 69b8a688..857d8a67 100644 --- a/cmd2/cmd2.py +++ b/cmd2/cmd2.py @@ -298,6 +298,10 @@ class Cmd(cmd.Cmd): DEFAULT_EDITOR = utils.find_editor() + INTERNAL_COMMAND_EPILOG = ( + "Notes:\n This command is for internal use and is not intended to be called from the\n command line." + ) + # Sorting keys for strings ALPHABETICAL_SORT_KEY = utils.norm_fold NATURAL_SORT_KEY = utils.natural_keys @@ -3251,7 +3255,7 @@ def _cmdloop(self) -> None: # Top-level parser for alias @staticmethod def _build_alias_parser() -> Cmd2ArgumentParser: - alias_description = "Manage aliases." + alias_description = "Manage aliases\n\nAn alias is a command that enables replacement of a word by another string." alias_parser = argparse_custom.DEFAULT_ARGUMENT_PARSER(description=alias_description) alias_parser.add_subparsers(metavar='SUBCOMMAND', required=True) @@ -5405,7 +5409,7 @@ def _validate_prepostcmd_hook( raise TypeError(f'{func.__name__} does not have a declared return type, expected {data_type}') if signature.return_annotation != data_type: raise TypeError( - f'{func.__name__} has incompatible return type {signature.return_annotation}, expected ' f'{data_type}' + f'{func.__name__} has incompatible return type {signature.return_annotation}, expected {data_type}' ) def register_precmd_hook(self, func: Callable[[plugin.PrecommandData], plugin.PrecommandData]) -> None: diff --git a/cmd2/decorators.py b/cmd2/decorators.py index a46e9695..6d427378 100644 --- a/cmd2/decorators.py +++ b/cmd2/decorators.py @@ -88,7 +88,7 @@ def _parse_positionals(args: tuple[Any, ...]) -> tuple['cmd2.Cmd', Union[Stateme Cmd, ) - if (isinstance(arg, Cmd) or isinstance(arg, CommandSet)) and len(args) > pos: + if isinstance(arg, (Cmd, CommandSet)) and len(args) > pos + 1: if isinstance(arg, CommandSet): arg = arg._cmd next_arg = args[pos + 1] @@ -97,7 +97,7 @@ def _parse_positionals(args: tuple[Any, ...]) -> tuple['cmd2.Cmd', Union[Stateme # This shouldn't happen unless we forget to pass statement in `Cmd.onecmd` or # somehow call the unbound class method. - raise TypeError('Expected arguments: cmd: cmd2.Cmd, statement: Union[Statement, str] Not found') # pragma: no cover + raise TypeError('Expected arguments: cmd: cmd2.Cmd, statement: Union[Statement, str] Not found') def _arg_swap(args: Union[Sequence[Any]], search_arg: Any, *replace_arg: Any) -> list[Any]: @@ -115,7 +115,7 @@ def _arg_swap(args: Union[Sequence[Any]], search_arg: Any, *replace_arg: Any) -> return args_list -#: Function signature for an Command Function that accepts a pre-processed argument list from user input +#: Function signature for a command function that accepts a pre-processed argument list from user input #: and optionally returns a boolean ArgListCommandFuncOptionalBoolReturn = Callable[[CommandParent, list[str]], Optional[bool]] #: Function signature for an Command Function that accepts a pre-processed argument list from user input @@ -125,7 +125,7 @@ def _arg_swap(args: Union[Sequence[Any]], search_arg: Any, *replace_arg: Any) -> #: and returns Nothing ArgListCommandFuncNoneReturn = Callable[[CommandParent, list[str]], None] -#: Aggregate of all accepted function signatures for Command Functions that accept a pre-processed argument list +#: Aggregate of all accepted function signatures for command functions that accept a pre-processed argument list ArgListCommandFunc = Union[ ArgListCommandFuncOptionalBoolReturn[CommandParent], ArgListCommandFuncBoolReturn[CommandParent], @@ -246,21 +246,29 @@ def _set_parser_prog(parser: argparse.ArgumentParser, prog: str) -> None: req_args.append(action.dest) -#: Function signature for a Command Function that uses an argparse.ArgumentParser to process user input -#: and optionally returns a boolean +#: Function signatures for command functions that use an argparse.ArgumentParser to process user input +#: and optionally return a boolean ArgparseCommandFuncOptionalBoolReturn = Callable[[CommandParent, argparse.Namespace], Optional[bool]] -#: Function signature for a Command Function that uses an argparse.ArgumentParser to process user input -#: and returns a boolean +ArgparseCommandFuncWithUnknownArgsOptionalBoolReturn = Callable[[CommandParent, argparse.Namespace, list[str]], Optional[bool]] + +#: Function signatures for command functions that use an argparse.ArgumentParser to process user input +#: and return a boolean ArgparseCommandFuncBoolReturn = Callable[[CommandParent, argparse.Namespace], bool] -#: Function signature for an Command Function that uses an argparse.ArgumentParser to process user input -#: and returns nothing +ArgparseCommandFuncWithUnknownArgsBoolReturn = Callable[[CommandParent, argparse.Namespace, list[str]], bool] + +#: Function signatures for command functions that use an argparse.ArgumentParser to process user input +#: and return nothing ArgparseCommandFuncNoneReturn = Callable[[CommandParent, argparse.Namespace], None] +ArgparseCommandFuncWithUnknownArgsNoneReturn = Callable[[CommandParent, argparse.Namespace, list[str]], None] -#: Aggregate of all accepted function signatures for an argparse Command Function +#: Aggregate of all accepted function signatures for an argparse command function ArgparseCommandFunc = Union[ ArgparseCommandFuncOptionalBoolReturn[CommandParent], + ArgparseCommandFuncWithUnknownArgsOptionalBoolReturn[CommandParent], ArgparseCommandFuncBoolReturn[CommandParent], + ArgparseCommandFuncWithUnknownArgsBoolReturn[CommandParent], ArgparseCommandFuncNoneReturn[CommandParent], + ArgparseCommandFuncWithUnknownArgsNoneReturn[CommandParent], ] diff --git a/docs/api/index.md b/docs/api/index.md index d57e37a7..a427e00b 100644 --- a/docs/api/index.md +++ b/docs/api/index.md @@ -6,17 +6,17 @@ If a release of this library changes any of the items documented here, the versi ## Modules -- [cmd2.Cmd](./cmd.md) - functions and attributes of the main class in this library -- [cmd2.ansi](./ansi.md) - convenience classes and functions for generating ANSI escape sequences to style text in the terminal -- [cmd2.argparse_completer](./argparse_completer.md) - classes for `argparse`-based tab completion -- [cmd2.argparse_custom](./argparse_custom.md) - classes and functions for extending `argparse` -- [cmd2.command_definition](./command_definition.md) - supports the definition of commands in separate classes to be composed into cmd2.Cmd -- [cmd2.constants](./constants.md) - just like it says on the tin -- [cmd2.decorators](./decorators.md) - decorators for `cmd2` commands -- [cmd2.exceptions](./exceptions.md) - custom `cmd2` exceptions -- [cmd2.history](./history.md) - classes for storing the history of previously entered commands -- [cmd2.parsing](./parsing.md) - classes for parsing and storing user input -- [cmd2.plugin](./plugin.md) - data classes for hook methods -- [cmd2.py_bridge](./py_bridge.md) - classes for bridging calls from the embedded python environment to the host app -- [cmd2.table_creator](./table_creator.md) - table creation module -- [cmd2.utils](./utils.md) - various utility classes and functions +- [cmd2.Cmd](./cmd.md) - functions and attributes of the main class in this library +- [cmd2.ansi](./ansi.md) - convenience classes and functions for generating ANSI escape sequences to style text in the terminal +- [cmd2.argparse_completer](./argparse_completer.md) - classes for `argparse`-based tab completion +- [cmd2.argparse_custom](./argparse_custom.md) - classes and functions for extending `argparse` +- [cmd2.command_definition](./command_definition.md) - supports the definition of commands in separate classes to be composed into cmd2.Cmd +- [cmd2.constants](./constants.md) - just like it says on the tin +- [cmd2.decorators](./decorators.md) - decorators for `cmd2` commands +- [cmd2.exceptions](./exceptions.md) - custom `cmd2` exceptions +- [cmd2.history](./history.md) - classes for storing the history of previously entered commands +- [cmd2.parsing](./parsing.md) - classes for parsing and storing user input +- [cmd2.plugin](./plugin.md) - data classes for hook methods +- [cmd2.py_bridge](./py_bridge.md) - classes for bridging calls from the embedded python environment to the host app +- [cmd2.table_creator](./table_creator.md) - table creation module +- [cmd2.utils](./utils.md) - various utility classes and functions diff --git a/docs/doc_conventions.md b/docs/doc_conventions.md index 2c6caeae..072d690e 100644 --- a/docs/doc_conventions.md +++ b/docs/doc_conventions.md @@ -6,10 +6,10 @@ Follow the [Documentation Principles](http://www.writethedocs.org/guide/writing/ In addition: -- We have gone to great lengths to retain compatibility with the standard library cmd, the documentation should make it easy for developers to understand how to move from cmd to cmd2, and what benefits that will provide -- We should provide both descriptive and reference documentation. -- API reference documentation should be generated from docstrings in the code -- Documentation should include rich hyperlinking to other areas of the documentation, and to the API reference +- We have gone to great lengths to retain compatibility with the standard library cmd, the documentation should make it easy for developers to understand how to move from cmd to cmd2, and what benefits that will provide +- We should provide both descriptive and reference documentation. +- API reference documentation should be generated from docstrings in the code +- Documentation should include rich hyperlinking to other areas of the documentation, and to the API reference ## Style Checker @@ -19,9 +19,9 @@ We strongly encourage all developers to use [Prettier](https://prettier.io/) for All source files in the documentation must: -- have all lower case file names -- if the name has multiple words, separate them with an underscore -- end in '.rst' +- have all lower case file names +- if the name has multiple words, separate them with an underscore +- end in '.rst' ## Indenting @@ -39,8 +39,8 @@ Reference the [Markdown Basic Syntax](https://www.markdownguide.org/basic-syntax Code blocks can be created in two ways: -- Indent the block - this will show as a monospace code block, but won't include highighting -- use the triple backticks followed by the code language, e.e. `python` and close with triple backticks +- Indent the block - this will show as a monospace code block, but won't include highighting +- use the triple backticks followed by the code language, e.e. `python` and close with triple backticks If you want to show non-Python code, like shell commands, then use a different language such as `javascript`, `shell`, `json`, etc. diff --git a/docs/examples/alternate_event_loops.md b/docs/examples/alternate_event_loops.md index 1b9ebcdc..8fb024a6 100644 --- a/docs/examples/alternate_event_loops.md +++ b/docs/examples/alternate_event_loops.md @@ -56,6 +56,6 @@ The `cmd2.Cmd.onecmd_plus_hooks()` method will do the following to execute a sin Running in this fashion enables the ability to integrate with an external event loop. However, how to integrate with any specific event loop is beyond the scope of this documentation. Please note that running in this fashion comes with several disadvantages, including: -- Requires the developer to write more code -- Does not support transcript testing -- Does not allow commands at invocation via command-line arguments +- Requires the developer to write more code +- Does not support transcript testing +- Does not allow commands at invocation via command-line arguments diff --git a/docs/examples/examples.md b/docs/examples/examples.md new file mode 100644 index 00000000..1a14e7fa --- /dev/null +++ b/docs/examples/examples.md @@ -0,0 +1,5 @@ +# List of cmd2 examples + +{% + include-markdown "../../examples/README.md" +%} diff --git a/docs/examples/first_app.md b/docs/examples/first_app.md index 4e95a767..bd55225d 100644 --- a/docs/examples/first_app.md +++ b/docs/examples/first_app.md @@ -2,14 +2,14 @@ Here's a quick walkthrough of a simple application which demonstrates 8 features of `cmd2`: -- [Settings](../features/settings.md) -- [Commands](../features/commands.md) -- [Argument Processing](../features/argument_processing.md) -- [Generating Output](../features/generating_output.md) -- [Help](../features/help.md) -- [Shortcuts](../features/shortcuts_aliases_macros.md#shortcuts) -- [Multiline Commands](../features/multiline_commands.md) -- [History](../features/history.md) +- [Settings](../features/settings.md) +- [Commands](../features/commands.md) +- [Argument Processing](../features/argument_processing.md) +- [Generating Output](../features/generating_output.md) +- [Help](../features/help.md) +- [Shortcuts](../features/shortcuts_aliases_macros.md#shortcuts) +- [Multiline Commands](../features/multiline_commands.md) +- [History](../features/history.md) If you don't want to type as we go, here is the complete source (you can click to expand and then click the **Copy** button in the top-right): @@ -215,17 +215,17 @@ Notice the prompt changes to indicate that input is still ongoing. `cmd2` will c Users can access command history using two methods: -- the [readline](https://docs.python.org/3/library/readline.html) library which provides a python interface to the [GNU readline library](https://en.wikipedia.org/wiki/GNU_Readline) -- the `history` command which is built-in to `cmd2` +- the [readline](https://docs.python.org/3/library/readline.html) library which provides a python interface to the [GNU readline library](https://en.wikipedia.org/wiki/GNU_Readline) +- the `history` command which is built-in to `cmd2` From the prompt in a `cmd2`-based application, you can press `Control-p` to move to the previously entered command, and `Control-n` to move to the next command. You can also search through the command history using `Control-r`. The [GNU Readline User Manual](http://man7.org/linux/man-pages/man3/readline.3.html) has all the details, including all the available commands, and instructions for customizing the key bindings. The `history` command allows a user to view the command history, and select commands from history by number, range, string search, or regular expression. With the selected commands, users can: -- re-run the commands -- edit the selected commands in a text editor, and run them after the text editor exits -- save the commands to a file -- run the commands, saving both the commands and their output to a file +- re-run the commands +- edit the selected commands in a text editor, and run them after the text editor exits +- save the commands to a file +- run the commands, saving both the commands and their output to a file Learn more about the `history` command by typing `history -h` at any `cmd2` input prompt, or by exploring [Command History For Users](../features/history.md#for-users). @@ -233,6 +233,6 @@ Learn more about the `history` command by typing `history -h` at any `cmd2` inpu You've just created a simple, but functional command line application. With minimal work on your part, the application leverages many robust features of `cmd2`. To learn more you can: -- Dive into all of the [Features](../features/index.md) that `cmd2` provides -- Look at more [Examples](../examples/index.md) -- Browse the [API Reference](../api/index.md) +- Dive into all of the [Features](../features/index.md) that `cmd2` provides +- Look at more [Examples](../examples/index.md) +- Browse the [API Reference](../api/index.md) diff --git a/docs/examples/index.md b/docs/examples/index.md index 077c63c1..23001e97 100644 --- a/docs/examples/index.md +++ b/docs/examples/index.md @@ -4,5 +4,6 @@ - [First Application](first_app.md) - [Alternate Event Loops](alternate_event_loops.md) +- [List of cmd2 examples](examples.md) diff --git a/docs/features/completion.md b/docs/features/completion.md index 86d48030..b3b7ccc0 100644 --- a/docs/features/completion.md +++ b/docs/features/completion.md @@ -2,10 +2,10 @@ `cmd2.Cmd` adds tab completion of file system paths for all built-in commands where it makes sense, including: -- [edit](./builtin_commands.md#edit) -- [run_pyscript](./builtin_commands.md#run_pyscript) -- [run_script](./builtin_commands.md#run_script) -- [shell](./builtin_commands.md#shell) +- [edit](./builtin_commands.md#edit) +- [run_pyscript](./builtin_commands.md#run_pyscript) +- [run_script](./builtin_commands.md#run_script) +- [shell](./builtin_commands.md#shell) `cmd2.Cmd` also adds tab completion of shell commands to the [shell](./builtin_commands.md#shell) command. @@ -28,31 +28,31 @@ complete_bar = functools.partialmethod(cmd2.Cmd.path_complete, path_filter=os.pa `cmd2` provides the following tab completion functions -- `cmd2.Cmd.basic_complete` - helper method for tab completion against a list +- `cmd2.Cmd.basic_complete` - helper method for tab completion against a list -- `cmd2.Cmd.path_complete` - helper method provides flexible tab completion of file system paths +- `cmd2.Cmd.path_complete` - helper method provides flexible tab completion of file system paths - > - See the [paged_output](https://github.com/python-cmd2/cmd2/blob/master/examples/paged_output.py) example for a simple use case - > - See the [python_scripting](https://github.com/python-cmd2/cmd2/blob/master/examples/python_scripting.py) example for a more full-featured use case + > - See the [paged_output](https://github.com/python-cmd2/cmd2/blob/master/examples/paged_output.py) example for a simple use case + > - See the [python_scripting](https://github.com/python-cmd2/cmd2/blob/master/examples/python_scripting.py) example for a more full-featured use case -- `cmd2.Cmd.delimiter_complete` - helper method for tab completion against a list but each match is split on a delimiter +- `cmd2.Cmd.delimiter_complete` - helper method for tab completion against a list but each match is split on a delimiter - > - See the [basic_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/basic_completion.py) example for a demonstration of how to use this feature + > - See the [basic_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/basic_completion.py) example for a demonstration of how to use this feature -- `cmd2.Cmd.flag_based_complete` - helper method for tab completion based on a particular flag preceding the token being completed +- `cmd2.Cmd.flag_based_complete` - helper method for tab completion based on a particular flag preceding the token being completed -- `cmd2.Cmd.index_based_complete` - helper method for tab completion based on a fixed position in the input string +- `cmd2.Cmd.index_based_complete` - helper method for tab completion based on a fixed position in the input string - > - See the [basic_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/basic_completion.py) example for a demonstration of how to use these features - > - `flag_based_complete()` and `index_based_complete()` are basic methods and should only be used if you are not familiar with argparse. The recommended approach for tab completing positional tokens and flags is to use [argparse-based](#argparse-based) completion. + > - See the [basic_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/basic_completion.py) example for a demonstration of how to use these features + > - `flag_based_complete()` and `index_based_complete()` are basic methods and should only be used if you are not familiar with argparse. The recommended approach for tab completing positional tokens and flags is to use [argparse-based](#argparse-based) completion. ## Raising Exceptions During Completion There are times when an error occurs while tab completing and a message needs to be reported to the user. These include the following example cases: -- Reading a database to retrieve a tab completion data set failed -- A previous command line argument that determines the data set being completed is invalid -- Tab completion hints +- Reading a database to retrieve a tab completion data set failed +- A previous command line argument that determines the data set being completed is invalid +- Tab completion hints `cmd2` provides the `cmd2.exceptions.CompletionError` exception class for this capability. If an error occurs in which it is more desirable to display a message than a stack trace, then raise a `CompletionError`. By default, the message displays in red like an error. However, `CompletionError` has a member called `apply_style`. Set this False if the error style should not be applied. For instance, `ArgparseCompleter` sets it to False when displaying completion hints. @@ -62,9 +62,9 @@ When using one the argparse-based [cmd2.decorators](../api/decorators.md), `cmd2 Tab completion of argument values can be configured by using one of three parameters to `argparse.ArgumentParser.add_argument` -- `choices` -- `choices_provider` -- `completer` +- `choices` +- `choices_provider` +- `completer` See the [arg_decorators](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_decorators.py) or [colors](https://github.com/python-cmd2/cmd2/blob/master/examples/colors.py) example for a demonstration of how to use the `choices` parameter. See the [argparse_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_completion.py) example for a demonstration of how to use the `choices_provider` parameter. See the [arg_decorators](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_decorators.py) or [argparse_completion](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_completion.py) example for a demonstration of how to use the `completer` parameter. diff --git a/docs/features/generating_output.md b/docs/features/generating_output.md index 679677b3..ce23b5f3 100644 --- a/docs/features/generating_output.md +++ b/docs/features/generating_output.md @@ -56,12 +56,12 @@ You can add your own [ANSI escape sequences](https://en.wikipedia.org/wiki/ANSI_ After adding the desired escape sequences to your output, you should use one of these methods to present the output to the user: -- `cmd2.Cmd.poutput` -- `cmd2.Cmd.perror` -- `cmd2.Cmd.pwarning` -- `cmd2.Cmd.pexcept` -- `cmd2.Cmd.pfeedback` -- `cmd2.Cmd.ppaged` +- `cmd2.Cmd.poutput` +- `cmd2.Cmd.perror` +- `cmd2.Cmd.pwarning` +- `cmd2.Cmd.pexcept` +- `cmd2.Cmd.pfeedback` +- `cmd2.Cmd.ppaged` These methods all honor the [allow_style](./settings.md#allow_style) setting, which users can modify to control whether these escape codes are passed through to the terminal or not. @@ -69,9 +69,9 @@ These methods all honor the [allow_style](./settings.md#allow_style) setting, wh If you would like to generate output which is left, center, or right aligned within a specified width or the terminal width, the following functions can help: -- `cmd2.utils.align_left` -- `cmd2.utils.align_center` -- `cmd2.utils.align_right` +- `cmd2.utils.align_left` +- `cmd2.utils.align_center` +- `cmd2.utils.align_right` These functions differ from Python's string justifying functions in that they support characters with display widths greater than 1. Additionally, ANSI style sequences are safely ignored and do not count toward the display width. This means colored text is supported. If text has line breaks, then each line is aligned independently. diff --git a/docs/features/history.md b/docs/features/history.md index fa4893be..d566587c 100644 --- a/docs/features/history.md +++ b/docs/features/history.md @@ -99,11 +99,11 @@ If your regular expression contains any characters that `argparse` finds interes This all sounds great, but doesn't it seem like a bit of overkill to have all these ways to select commands if all we can do is display them? Turns out, displaying history commands is just the beginning. The history command can perform many other actions: -- running previously entered commands -- saving previously entered commands to a text file -- opening previously entered commands in your favorite text editor -- running previously entered commands, saving the commands and their output to a text file -- clearing the history of entered commands +- running previously entered commands +- saving previously entered commands to a text file +- opening previously entered commands in your favorite text editor +- running previously entered commands, saving the commands and their output to a text file +- clearing the history of entered commands Each of these actions is invoked using a command line option. The `-r` or `--run` option runs one or more previously entered commands. To run command number 1: diff --git a/docs/features/hooks.md b/docs/features/hooks.md index ada2844f..7ce38559 100644 --- a/docs/features/hooks.md +++ b/docs/features/hooks.md @@ -54,16 +54,16 @@ The approach of registering hooks instead of overriding methods allows multiple There are numerous attributes on `cmd2.Cmd` which affect application behavior upon entering or during the command loop: -- `cmd2.Cmd.intro` - if provided this serves as the intro banner printed once at start of application, after `cmd2.Cmd.preloop` is called -- `cmd2.Cmd.prompt` - see [Prompt](./prompt.md) for more information -- `cmd2.Cmd.continuation_prompt` - The prompt issued to solicit input for the 2nd and subsequent lines of a `multiline command [Multiline Commands](./multiline_commands.md) -- `cmd2.Cmd.echo` - if `True` write the prompt and the command into the output stream +- `cmd2.Cmd.intro` - if provided this serves as the intro banner printed once at start of application, after `cmd2.Cmd.preloop` is called +- `cmd2.Cmd.prompt` - see [Prompt](./prompt.md) for more information +- `cmd2.Cmd.continuation_prompt` - The prompt issued to solicit input for the 2nd and subsequent lines of a `multiline command [Multiline Commands](./multiline_commands.md) +- `cmd2.Cmd.echo` - if `True` write the prompt and the command into the output stream In addition, several arguments to `cmd2.Cmd.__init__` also affect the command loop behavior: -- `allow_cli_args` - allows commands to be specified on the operating system command line which are executed before the command processing loop begins -- `transcript_files` - see [Transcripts](./transcripts.md) for more information -- `startup_script` - run a script on initialization. See [Scripting](./scripting.md) for more information +- `allow_cli_args` - allows commands to be specified on the operating system command line which are executed before the command processing loop begins +- `transcript_files` - see [Transcripts](./transcripts.md) for more information +- `startup_script` - run a script on initialization. See [Scripting](./scripting.md) for more information ## Command Processing Loop @@ -91,9 +91,9 @@ Postparsing, precommand, and postcommand hook methods share some common ways to If a hook raises an exception: -- no more hooks (except command finalization hooks) of any kind will be called -- if the command has not yet been executed, it will not be executed -- the exception message will be displayed for the user. +- no more hooks (except command finalization hooks) of any kind will be called +- if the command has not yet been executed, it will not be executed +- the exception message will be displayed for the user. Specific types of hook methods have additional options as described below. @@ -101,10 +101,10 @@ Specific types of hook methods have additional options as described below. Postparsing hooks are called after the user input has been parsed but before execution of the command. These hooks can be used to: -- modify the user input -- run code before every command executes -- cancel execution of the current command -- exit the application +- modify the user input +- run code before every command executes +- cancel execution of the current command +- exit the application When postparsing hooks are called, output has not been redirected, nor has the timer for command execution been started. @@ -142,10 +142,10 @@ def myhookmethod(self, params: cmd2.plugin.PostparsingData) -> cmd2.plugin.Postp If a postparsing hook returns a `cmd2.plugin.PostparsingData` object with the `cmd2.plugin.PostparsingData.stop` attribute set to `True`: -- no more hooks of any kind (except [Command Finalization Hooks](#command-finalization-hooks)) will be called -- the command will not be executed -- no error message will be displayed to the user -- the application will exit +- no more hooks of any kind (except [Command Finalization Hooks](#command-finalization-hooks)) will be called +- the command will not be executed +- no error message will be displayed to the user +- the application will exit ## Precommand Hooks @@ -201,8 +201,8 @@ Any postcommand hook can change the value of the `stop` attribute before returni To purposefully and silently skip postcommand hooks, commands can raise any of of the following exceptions. -- `cmd2.exceptions.SkipPostcommandHooks` -- `cmd2.exceptions.Cmd2ArgparseError` +- `cmd2.exceptions.SkipPostcommandHooks` +- `cmd2.exceptions.Cmd2ArgparseError` ## Command Finalization Hooks diff --git a/docs/features/packaging.md b/docs/features/packaging.md index 75031393..bfbf7b6a 100644 --- a/docs/features/packaging.md +++ b/docs/features/packaging.md @@ -18,20 +18,20 @@ This convenient blog post will show you [How to "Dockerize" Your Python Applicat For developers wishing to package a `cmd2` application into a single binary image or compressed file, we can recommend all of the following based on personal and professional experience: -- [PyInstaller](https://www.pyinstaller.org) - - Freeze (package) Python programs into stand-alone executables - - PyInstaller bundles a Python application and all its dependencies into a single package - - The user can run the packaged app without installing a Python interpreter or any modules -- [Nuitka](https://nuitka.net) - - Nuitka is a Python compiler written in Python - - You feed it your Python app, it does a lot of clever things, and spits out an executable or extension module - - This can be particularly convenient if you wish to obfuscate the Python source code behind your application -- [Conda Constructor](https://github.com/conda/constructor) - - Allows you to create a custom Python distro based on [Miniconda](https://docs.conda.io/en/latest/miniconda.html) -- [PyOxidizer](https://github.com/indygreg/PyOxidizer) - - PyOxidizer is a utility for producing binaries that embed Python - - PyOxidizer is capable of producing a single file executable - with a copy of Python and all its dependencies statically linked and all resources embedded in the executable - - You can copy a single executable file to another machine and run a Python application contained within. It just works. +- [PyInstaller](https://www.pyinstaller.org) + - Freeze (package) Python programs into stand-alone executables + - PyInstaller bundles a Python application and all its dependencies into a single package + - The user can run the packaged app without installing a Python interpreter or any modules +- [Nuitka](https://nuitka.net) + - Nuitka is a Python compiler written in Python + - You feed it your Python app, it does a lot of clever things, and spits out an executable or extension module + - This can be particularly convenient if you wish to obfuscate the Python source code behind your application +- [Conda Constructor](https://github.com/conda/constructor) + - Allows you to create a custom Python distro based on [Miniconda](https://docs.conda.io/en/latest/miniconda.html) +- [PyOxidizer](https://github.com/indygreg/PyOxidizer) + - PyOxidizer is a utility for producing binaries that embed Python + - PyOxidizer is capable of producing a single file executable - with a copy of Python and all its dependencies statically linked and all resources embedded in the executable + - You can copy a single executable file to another machine and run a Python application contained within. It just works. !!! warning diff --git a/docs/features/plugins.md b/docs/features/plugins.md index 9491aadc..e7a91abe 100644 --- a/docs/features/plugins.md +++ b/docs/features/plugins.md @@ -36,8 +36,8 @@ class Example(cmd2_myplugin.MyPlugin, cmd2.Cmd): Note how the plugin must be inherited (or mixed in) before `cmd2.Cmd`. This is required for two reasons: -- The `cmd.Cmd.__init__` method in the python standard library does not call `super().__init__()`. Because of this oversight, if you don't inherit from `MyPlugin` first, the `MyPlugin.__init__()` method will never be called. -- You may want your plugin to be able to override methods from `cmd2.Cmd`. If you mixin the plugin after `cmd2.Cmd`, the python method resolution order will call [cmd2.Cmd][] methods before it calls those in your plugin. +- The `cmd.Cmd.__init__` method in the python standard library does not call `super().__init__()`. Because of this oversight, if you don't inherit from `MyPlugin` first, the `MyPlugin.__init__()` method will never be called. +- You may want your plugin to be able to override methods from `cmd2.Cmd`. If you mixin the plugin after `cmd2.Cmd`, the python method resolution order will call [cmd2.Cmd][] methods before it calls those in your plugin. ## Add commands diff --git a/docs/features/redirection.md b/docs/features/redirection.md index 15497a67..e92eec3a 100644 --- a/docs/features/redirection.md +++ b/docs/features/redirection.md @@ -8,8 +8,8 @@ As in POSIX shells, output of a command can be redirected and/or piped. This fea Redirecting the output of a `cmd2` command to a file works just like in POSIX shells: -- send to a file with `>`, as in `mycommand args > filename.txt` -- append to a file with `>>`, as in `mycommand args >> filename.txt` +- send to a file with `>`, as in `mycommand args > filename.txt` +- append to a file with `>>`, as in `mycommand args >> filename.txt` If you need to include any of these redirection characters in your command, you can enclose them in quotation marks, `mycommand 'with > in the argument'`. @@ -17,14 +17,14 @@ If you need to include any of these redirection characters in your command, you `cmd2` output redirection supports an additional feature not found in most shells - if the file name following the `>` or `>>` is left blank, then the output is redirected to the operating system clipboard so that it can then be pasted into another program. -- overwrite the clipboard with `mycommand args >` -- append to the clipboard with `mycommand args >>` +- overwrite the clipboard with `mycommand args >` +- append to the clipboard with `mycommand args >>` ## Pipes Piping the output of a `cmd2` command to a shell command works just like in POSIX shells: -- pipe as input to a shell command with `|`, as in `mycommand args | wc` +- pipe as input to a shell command with `|`, as in `mycommand args | wc` ## Multiple Pipes and Redirection @@ -53,5 +53,5 @@ The above runs the **help** command, pipes its output to **grep** searching for Some limitations apply to redirection and piping within `cmd2` applications: -- Can only pipe to shell commands, not other `cmd2` application commands -- **stdout** gets redirected/piped, **stderr** does not +- Can only pipe to shell commands, not other `cmd2` application commands +- **stdout** gets redirected/piped, **stderr** does not diff --git a/docs/features/scripting.md b/docs/features/scripting.md index ba4c5cd1..940a50da 100644 --- a/docs/features/scripting.md +++ b/docs/features/scripting.md @@ -10,9 +10,9 @@ A command script contains a sequence of commands typed at the the prompt of a `c Command scripts can be created in several ways: -- creating a text file using any method of your choice -- using the built-in [edit](./builtin_commands.md#edit) command to create or edit an existing text file -- saving previously entered commands to a script file using [history -s](./history.md#for-users) +- creating a text file using any method of your choice +- using the built-in [edit](./builtin_commands.md#edit) command to create or edit an existing text file +- saving previously entered commands to a script file using [history -s](./history.md#for-users) If you create create a text file from scratch, just include one command per line, exactly as you would type it inside a `cmd2` application. @@ -59,8 +59,8 @@ app(‘command args’) where: -- `app` is a configurable name which can be changed by setting the `cmd2.Cmd.py_bridge_name` attribute -- `command` and `args` are entered exactly like they would be entered by a user of your application. +- `app` is a configurable name which can be changed by setting the `cmd2.Cmd.py_bridge_name` attribute +- `command` and `args` are entered exactly like they would be entered by a user of your application. Using fstrings tends to be the most straight forward and easily readable way to provide parameters.: diff --git a/docs/features/settings.md b/docs/features/settings.md index 8d03da07..29f59619 100644 --- a/docs/features/settings.md +++ b/docs/features/settings.md @@ -10,18 +10,18 @@ Settings provide a mechanism for a user to control the behavior of a `cmd2` base Output generated by `cmd2` programs may contain ANSI escape sequences which instruct the terminal to apply colors or text styling (i.e. bold) to the output. The `allow_style` setting controls the behavior of these escape sequences in output generated with any of the following methods: -- **`cmd2.Cmd.poutput`** -- **`cmd2.Cmd.perror`** -- **`cmd2.Cmd.pwarning`** -- **`cmd2.Cmd.pexcept`** -- **`cmd2.Cmd.pfeedback`** -- **`cmd2.Cmd.ppaged`** +- **`cmd2.Cmd.poutput`** +- **`cmd2.Cmd.perror`** +- **`cmd2.Cmd.pwarning`** +- **`cmd2.Cmd.pexcept`** +- **`cmd2.Cmd.pfeedback`** +- **`cmd2.Cmd.ppaged`** This setting can be one of three values: -- `Never` - all ANSI escape sequences which instruct the terminal to style output are stripped from the output. -- `Terminal` - (the default value) pass through ANSI escape sequences when the output is being sent to the terminal, but if the output is redirected to a pipe or a file the escape sequences are stripped. -- `Always` - ANSI escape sequences are always passed through to the output +- `Never` - all ANSI escape sequences which instruct the terminal to style output are stripped from the output. +- `Terminal` - (the default value) pass through ANSI escape sequences when the output is being sent to the terminal, but if the output is redirected to a pipe or a file the escape sequences are stripped. +- `Always` - ANSI escape sequences are always passed through to the output ### always_show_hint diff --git a/docs/features/shortcuts_aliases_macros.md b/docs/features/shortcuts_aliases_macros.md index 3b1eebe8..5bef8955 100644 --- a/docs/features/shortcuts_aliases_macros.md +++ b/docs/features/shortcuts_aliases_macros.md @@ -4,10 +4,10 @@ Command shortcuts for long command names and common commands can make life more convenient for your users. Shortcuts are used without a space separating them from their arguments, like `!ls`. By default, the following shortcuts are defined: -- **`?`** - help -- **`!`** - shell: run as OS-level command -- **`@`** - run script file -- **`@@`** - run script file; filename is relative to current script location +- **`?`** - help +- **`!`** - shell: run as OS-level command +- **`@`** - run script file +- **`@@`** - run script file; filename is relative to current script location To define more shortcuts, update the dict `App.shortcuts` with the `{'shortcut': 'command_name'}` (omit `do_`): diff --git a/docs/javascripts/readthedocs.js b/docs/javascripts/readthedocs.js index 29f8c5d5..380dad3b 100644 --- a/docs/javascripts/readthedocs.js +++ b/docs/javascripts/readthedocs.js @@ -23,7 +23,7 @@ ${config.versions.active ${version.slug} - ` + `, ) .join("\n")} diff --git a/docs/overview/resources.md b/docs/overview/resources.md index db42e935..35e3ac09 100644 --- a/docs/overview/resources.md +++ b/docs/overview/resources.md @@ -2,7 +2,7 @@ Project related links and other resources: -- [cmd](https://docs.python.org/3/library/cmd.html) -- [cmd2 project page](https://github.com/python-cmd2/cmd2) -- [project bug tracker](https://github.com/python-cmd2/cmd2/issues) -- PyOhio 2019: [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf), [video](https://www.youtube.com/watch?v=pebeWrTqIIw), [examples](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples) +- [cmd](https://docs.python.org/3/library/cmd.html) +- [cmd2 project page](https://github.com/python-cmd2/cmd2) +- [project bug tracker](https://github.com/python-cmd2/cmd2/issues) +- PyOhio 2019: [slides](https://github.com/python-cmd2/talks/blob/master/PyOhio_2019/cmd2-PyOhio_2019.pdf), [video](https://www.youtube.com/watch?v=pebeWrTqIIw), [examples](https://github.com/python-cmd2/talks/tree/master/PyOhio_2019/examples) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..660ee68e --- /dev/null +++ b/examples/README.md @@ -0,0 +1,88 @@ +# cmd2 Examples + +The [examples](https://github.com/python-cmd2/cmd2/tree/master/examples) directory within the `cmd2` repository contains a number of simple self-contained examples which each demonstrate a few particular features of `cmd2`. None of them are representative of a full real-world complex `cmd2` application, if you are looking for that then see [Projects using cmd2](https://github.com/python-cmd2/cmd2?tab=readme-ov-file#projects-using-cmd2). + +## List of cmd2 examples + +Here is the list of examples in alphabetical order by filename along with a brief description of each: + +- [alias_startup.py](https://github.com/python-cmd2/cmd2/blob/master/examples/alias_startup.py) + - Demonstrates how to add custom command aliases and how to run an initialization script at startup +- [arg_decorators.py](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_decorators.py) + - Demonstrates how to use the `cmd2.with_argparser` decorator to specify command arguments using [argparse](https://docs.python.org/3/library/argparse.html) +- [arg_print.py](https://github.com/python-cmd2/cmd2/blob/master/examples/arg_print.py) + - Demonstrates how arguments and options get parsed and passed to commands and shows how shortcuts work +- [argparse_completion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/argparse_completion.py) + - Shows how to integrate tab-completion with argparse-based commands +- [async_printing.py](https://github.com/python-cmd2/cmd2/blob/master/examples/async_printing.py) + - Shows how to asynchronously print alerts, update the prompt in realtime, and change the window title +- [basic.py](https://github.com/python-cmd2/cmd2/blob/master/examples/basic.py) + - Shows how to add a command, add help for it, and create persistent command history for your application +- [basic_completion.py](https://github.com/python-cmd2/cmd2/blob/master/examples/basic_completion.py) + - Show how to enable custom tab completion by assigning a completer function to `do_*` commands +- [cmd2_as_argument.py](https://github.com/python-cmd2/cmd2/blob/master/examples/cmd_as_argument.py) + - Demonstrates how to accept and parse command-line arguments when invoking a cmd2 application +- [colors.py](https://github.com/python-cmd2/cmd2/blob/master/examples/colors.py) + - Show various ways of using colorized output within a cmd2 application +- [custom_parser.py](https://github.com/python-cmd2/cmd2/blob/master/examples/custom_parser.py) + - Demonstrates how to create your own customer `Cmd2ArgumentParser`; used by the `override_parser.py` example +- [decorator_example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/decorator_example.py) + - Shows how to use cmd2's various argparse decorators to processes command-line arguments +- [default_categories.py](https://github.com/python-cmd2/cmd2/blob/master/examples/default_categories.py) + - Demonstrates usage of `@with_default_category` decorator to group and categorize commands and `CommandSet` use +- [dynamic_commands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/dynamic_commands.py) + - Shows how `do_*` commands can be dynamically created programatically at runtime +- [environment.py](https://github.com/python-cmd2/cmd2/blob/master/examples/environment.py) + - Shows how to create custom `cmd2.Settable` parameters which serve as internal environment variables +- [event_loops.py](https://github.com/python-cmd2/cmd2/blob/master/examples/event_loops.py) + - Shows how to integrate a `cmd2` application with an external event loop which isn't managed by `cmd2` +- [example.py](https://github.com/python-cmd2/cmd2/blob/master/examples/example.py) + - This example is intended to demonstrate `cmd2's` build-in transcript testing capability +- [exit_code.py](https://github.com/python-cmd2/cmd2/blob/master/examples/exit_code.py) + - Show how to emit a non-zero exit code from your `cmd2` application when it exits +- [first_app.py](https://github.com/python-cmd2/cmd2/blob/master/examples/first_app.py) + - Short application that demonstrates 8 key features: Settings, Commands, Argument Parsing, Generating Output, Help, Shortcuts, Multiple Commands, and History +- [hello_cmd2.py](https://github.com/python-cmd2/cmd2/blob/master/examples/hello_cmd2.py) + - Completely bare-bones `cmd2` application suitable for rapid testing and debugging of `cmd2` itself +- [help_categories.py](https://github.com/python-cmd2/cmd2/blob/master/examples/help_categories.py) + - Demonstrates command categorization and its impact on the output of the built-in `help` command +- [hooks.py](https://github.com/python-cmd2/cmd2/blob/master/examples/hooks.py) + - Shows how to use various `cmd2` application lifecycle hooks +- [initialization.py](https://github.com/python-cmd2/cmd2/blob/master/examples/initialization.py) + - Shows how to colorize output, use multiline command, add persistent history, and more +- [migrating.py](https://github.com/python-cmd2/cmd2/blob/master/examples/migrating.py) + - A simple `cmd` application that you can migrate to `cmd2` by changing one line +- [modular_commands_basic.py](https://github.com/python-cmd2/cmd2/blob/master/examples/modular_commands_basic.py) + - Demonstrates based `CommandSet` usage +- [modular_commands_dynamic.py](https://github.com/python-cmd2/cmd2/blob/master/examples/modular_commands_dynamic.py) + - Demonstrates dynamic `CommandSet` loading and unloading +- [modular_commands_main.py](https://github.com/python-cmd2/cmd2/blob/master/examples/modular_commands_main.py) + - Complex example demonstrating a variety of methods to load `CommandSets` using a mix of command decorators +- [modular_subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/modular_subcommands.py) + - Shows how to dynamically add and remove subcommands at runtime using `CommandSets` +- [override-parser.py](https://github.com/python-cmd2/cmd2/blob/master/examples/override_parser.py) + - Shows how to override cmd2's default `Cmd2ArgumentParser` with your own customer parser class +- [paged_output.py](https://github.com/python-cmd2/cmd2/blob/master/examples/paged_output.py) + - Shows how to use output pagination within `cmd2` apps via the `ppaged` method +- [persistent_history.py](https://github.com/python-cmd2/cmd2/blob/master/examples/persistent_history.py) + - Shows how to enable persistent history in your `cmd2` application +- [pirate.py](https://github.com/python-cmd2/cmd2/blob/master/examples/pirate.py) + - Demonstrates many features including colorized output, multiline commands, shorcuts, defaulting to shell, etc. +- [python_scripting.py](https://github.com/python-cmd2/cmd2/blob/master/examples/python_scripting.py) + - Shows how cmd2's built-in `run_pyscript` command can provide advanced Python scripting of cmd2 applications +- [read_input.py](https://github.com/python-cmd2/cmd2/blob/master/examples/read_input.py) + - Demonstrates the various ways to call `cmd2.Cmd.read_input()` for input history and tab completion +- [remove_builtin_commands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/remove_builtin_commands.py) + - Shows how to remove any built-in cmd2 commands you do not want to be present in your cmd2 application +- [remove_settable.py](https://github.com/python-cmd2/cmd2/blob/master/examples/remove_settable.py) + - Shows how to remove any of the built-in cmd2 `Settables` you do not want in your cmd2 application +- [subcommands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/subcommands.py) + - Shows how to use `argparse` to easily support sub-commands within your cmd2 commands +- [table_creation.py](https://github.com/python-cmd2/cmd2/blob/master/examples/table_creation.py) + - Contains various examples of using cmd2's table creation capabilities +- [tmux_launch.sh](https://github.com/python-cmd2/cmd2/blob/master/examples/tmux_launch.sh) + - Shell script that launches two applications using tmux in different windows/tabs +- [tmux_split.sh](https://github.com/python-cmd2/cmd2/blob/master/examples/tmux_split.sh) + - Shell script that launches two applications using tmux in a split pane view +- [unicode_commands.py](https://github.com/python-cmd2/cmd2/blob/master/examples/unicode_commands.py) + - Shows that cmd2 supports unicode everywhere, including within command names diff --git a/examples/argparse_completion.py b/examples/argparse_completion.py index 6b706488..b1efe4e5 100755 --- a/examples/argparse_completion.py +++ b/examples/argparse_completion.py @@ -64,7 +64,7 @@ def choices_arg_tokens(self, arg_tokens: dict[str, list[str]]) -> list[str]: # Parser for example command example_parser = Cmd2ArgumentParser( - description="Command demonstrating tab completion with argparse\n" "Notice even the flags of this command tab complete" + description="Command demonstrating tab completion with argparse\nNotice even the flags of this command tab complete" ) # Tab complete from a list using argparse choices. Set metavar if you don't diff --git a/examples/migrating.py b/examples/migrating.py index 22efadab..199b78db 100755 --- a/examples/migrating.py +++ b/examples/migrating.py @@ -1,10 +1,11 @@ #!/usr/bin/env python # coding=utf-8 """ -A sample application for cmd which can be used to show how to migrate to cmd2. +A sample cmd application that shows how to trivially migrate a cmd application to use cmd2. """ -import cmd +# import cmd2 as cmd +import cmd # Comment this line and uncomment the one above to migrate to cmd2 import random diff --git a/examples/modular_commands/commandset_basic.py b/examples/modular_commands/commandset_basic.py index 4fe63bbf..59a08de0 100644 --- a/examples/modular_commands/commandset_basic.py +++ b/examples/modular_commands/commandset_basic.py @@ -4,7 +4,6 @@ """ from cmd2 import ( - Cmd, CommandSet, CompletionError, Statement, @@ -28,7 +27,7 @@ class BasicCompletionCommandSet(CommandSet): '/home/other user/tests.db', ] - def do_flag_based(self, cmd: Cmd, statement: Statement): + def do_flag_based(self, statement: Statement) -> None: """Tab completes arguments based on a preceding flag using flag_based_complete -f, --food [completes food items] -s, --sport [completes sports] @@ -36,7 +35,7 @@ def do_flag_based(self, cmd: Cmd, statement: Statement): """ self._cmd.poutput("Args: {}".format(statement.args)) - def complete_flag_based(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> list[str]: + def complete_flag_based(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: """Completion function for do_flag_based""" flag_dict = { # Tab complete food items after -f and --food flags in command line @@ -46,38 +45,38 @@ def complete_flag_based(self, cmd: Cmd, text: str, line: str, begidx: int, endid '-s': self.sport_item_strs, '--sport': self.sport_item_strs, # Tab complete using path_complete function after -p and --path flags in command line - '-p': cmd.path_complete, - '--path': cmd.path_complete, + '-p': self._cmd.path_complete, + '--path': self._cmd.path_complete, } - return cmd.flag_based_complete(text, line, begidx, endidx, flag_dict=flag_dict) + return self._cmd.flag_based_complete(text, line, begidx, endidx, flag_dict=flag_dict) - def do_index_based(self, cmd: Cmd, statement: Statement): + def do_index_based(self, statement: Statement) -> None: """Tab completes first 3 arguments using index_based_complete""" self._cmd.poutput("Args: {}".format(statement.args)) - def complete_index_based(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> list[str]: + def complete_index_based(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: """Completion function for do_index_based""" index_dict = { 1: self.food_item_strs, # Tab complete food items at index 1 in command line 2: self.sport_item_strs, # Tab complete sport items at index 2 in command line - 3: cmd.path_complete, # Tab complete using path_complete function at index 3 in command line + 3: self._cmd.path_complete, # Tab complete using path_complete function at index 3 in command line } - return cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict) + return self._cmd.index_based_complete(text, line, begidx, endidx, index_dict=index_dict) - def do_delimiter_complete(self, cmd: Cmd, statement: Statement): + def do_delimiter_complete(self, statement: Statement) -> None: """Tab completes files from a list using delimiter_complete""" self._cmd.poutput("Args: {}".format(statement.args)) - def complete_delimiter_complete(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> list[str]: - return cmd.delimiter_complete(text, line, begidx, endidx, match_against=self.file_strs, delimiter='/') + def complete_delimiter_complete(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: + return self._cmd.delimiter_complete(text, line, begidx, endidx, match_against=self.file_strs, delimiter='/') - def do_raise_error(self, cmd: Cmd, statement: Statement): + def do_raise_error(self, statement: Statement) -> None: """Demonstrates effect of raising CompletionError""" self._cmd.poutput("Args: {}".format(statement.args)) - def complete_raise_error(self, cmd: Cmd, text: str, line: str, begidx: int, endidx: int) -> list[str]: + def complete_raise_error(self, text: str, line: str, begidx: int, endidx: int) -> list[str]: """ CompletionErrors can be raised if an error occurs while tab completing. @@ -88,5 +87,5 @@ def complete_raise_error(self, cmd: Cmd, text: str, line: str, begidx: int, endi raise CompletionError("This is how a CompletionError behaves") @with_category('Not Basic Completion') - def do_custom_category(self, cmd: Cmd, statement: Statement): + def do_custom_category(self, statement: Statement) -> None: self._cmd.poutput('Demonstrates a command that bypasses the default category') diff --git a/examples/modular_commands_main.py b/examples/modular_commands_main.py index 00f5bce9..773e042b 100755 --- a/examples/modular_commands_main.py +++ b/examples/modular_commands_main.py @@ -40,7 +40,7 @@ def choices_provider(self) -> list[str]: # Parser for example command example_parser = Cmd2ArgumentParser( - description="Command demonstrating tab completion with argparse\n" "Notice even the flags of this command tab complete" + description="Command demonstrating tab completion with argparse\nNotice even the flags of this command tab complete" ) # Tab complete from a list using argparse choices. Set metavar if you don't diff --git a/examples/table_creation.py b/examples/table_creation.py index 485c4c05..3cffa45f 100755 --- a/examples/table_creation.py +++ b/examples/table_creation.py @@ -74,18 +74,18 @@ def basic_tables(): # Table data which demonstrates handling of wrapping and text styles data_list: list[list[Any]] = list() - data_list.append(["Billy Smith", "123 Sesame St.\n" "Fake Town, USA 33445", DollarFormatter(100333.03)]) + data_list.append(["Billy Smith", "123 Sesame St.\nFake Town, USA 33445", DollarFormatter(100333.03)]) data_list.append( [ "William Longfellow Marmaduke III", - "984 Really Long Street Name Which Will Wrap Nicely\n" "Apt 22G\n" "Pensacola, FL 32501", + "984 Really Long Street Name Which Will Wrap Nicely\nApt 22G\nPensacola, FL 32501", DollarFormatter(55135.22), ] ) data_list.append( [ "James " + blue("Bluestone"), - bold_yellow("This address has line feeds,\n" "text styles, and wrapping. ") + bold_yellow("This address has line feeds,\ntext styles, and wrapping. ") + blue("Style is preserved across lines."), DollarFormatter(300876.10), ] diff --git a/examples/tmux_launch.sh b/examples/tmux_launch.sh new file mode 100755 index 00000000..624459ac --- /dev/null +++ b/examples/tmux_launch.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env zsh + +# This script launches two applications using tmux in different windows/tabs. +# The user is required to enter the name of at least the first application. +# If the second isn't provided, then the user's default shell is launched for this. +# You must have tmux installed and that can be done using your operating system's package manager. +# +# See the tmux Wiki for info on how to use it: https://github.com/tmux/tmux/wiki. +# To shift focus between different windows in tmux use Ctrl-b followed by l (lowercase "L"). +# +# NOTE: If you have byobu installed, it is a wrapper around tmux and will likely run instead of tmux. +# For info on how to use Byobu, see: https://www.byobu.org/ +# To shift focus between windows/tabs in byobu, simply hit F3. + +# Function to print in red +print_red() { + echo -e "\e[31m$*\e[0m" +} + +if [ $# -eq 0 ]; + then + print_red "No arguments supplied and this script requires at least one" + exit 1 +fi + +FIRST_COMMAND=$1 + +if [ $# -eq 1 ] + then + SECOND_COMMAND=$SHELL + else + SECOND_COMMAND=$2 +fi + +tmux new-session -s "tmux window demo" -n "$FIRST_COMMAND" "$FIRST_COMMAND ;read" \; \ + new-window -n "$SECOND_COMMAND" "$SECOND_COMMAND ; read" \; previous-window \ No newline at end of file diff --git a/examples/tmux_split.sh b/examples/tmux_split.sh new file mode 100755 index 00000000..fc817007 --- /dev/null +++ b/examples/tmux_split.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env zsh + +# This script launches two applications using byobu in different tabs. +# The user is required to enter the name of at least the first application. +# If the second isn't provided, then the user's default shell is launched for this. +# +# byobu must be installed for this script to work and you can install it using your +# operating system package manager. For info on how to use Byobu, see: https://www.byobu.org/ +# +# To shift focus between tabs in byobu, just hit F3. + +# Function to print in red +print_red() { + echo -e "\e[31m$*\e[0m" +} + +if [ $# -eq 0 ]; + then + print_red "No arguments supplied and this script requires at least one" + exit 1 +fi + +FIRST_COMMAND=$1 + +if [ $# -eq 1 ] + then + SECOND_COMMAND=$SHELL + else + SECOND_COMMAND=$2 +fi + +tmux new-session -s "tmux split pane demo" "$FIRST_COMMAND ; read" \; \ + split-window "$SECOND_COMMAND ; read" \; \ + select-layout even-vertical \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index f0f086fb..e0767e90 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -2,7 +2,7 @@ site_name: cmd2 site_description: cmd2 - quickly build feature-rich and user-friendly interactive command line applications in Python. site_dir: build/html -site_url: !ENV [READTHEDOCS_CANONICAL_URL, https://cmd2.readthedocs.io/] +site_url: !ENV [READTHEDOCS_CANONICAL_URL, https://cmd2.readthedocs.io/] # Repository repo_name: cmd2 @@ -72,18 +72,18 @@ plugins: python: options: extensions: - - griffe_typingdoc + - griffe_typingdoc show_root_heading: true show_if_no_docstring: true preload_modules: - - argparse - - cmd + - argparse + - cmd inherited_members: true members_order: source separate_signature: true unwrap_annotated: true filters: - - '!^_' + - "!^_" merge_init_into_class: true docstring_section_style: spacy signature_crossrefs: true @@ -122,9 +122,9 @@ markdown_extensions: - pymdownx.smartsymbols - pymdownx.superfences: custom_fences: - - name: mermaid - class: mermaid - format: !!python/name:pymdownx.superfences.fence_code_format + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format - pymdownx.tabbed: alternate_style: true @@ -189,6 +189,7 @@ nav: - examples/index.md - examples/first_app.md - examples/alternate_event_loops.md + - examples/examples.md - Plugins: - plugins/index.md - plugins/external_test.md @@ -219,4 +220,4 @@ extra_css: # Include extra JS to setup Read the Docs addons integrations extra_javascript: - - javascripts/readthedocs.js \ No newline at end of file + - javascripts/readthedocs.js diff --git a/plugins/ext_test/CHANGELOG.md b/plugins/ext_test/CHANGELOG.md index 031d4227..d35f16d3 100644 --- a/plugins/ext_test/CHANGELOG.md +++ b/plugins/ext_test/CHANGELOG.md @@ -1,20 +1,22 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). ## 0.2.0 (2020-09-11) -* Updated documentation to reflect new home inside of main cmd2 repo. -* Updated python version requirements to match cmd2 + +- Updated documentation to reflect new home inside of main cmd2 repo. +- Updated python version requirements to match cmd2 ## 0.1.2 (2020-08-03) -* Bug Fixes - * Applied fix to match change in cmd2 APIs + +- Bug Fixes + - Applied fix to match change in cmd2 APIs ## 0.1.1 (2020-03-09) ### Added -- Initial contribution - +- Initial contribution diff --git a/plugins/ext_test/README.md b/plugins/ext_test/README.md index 6f8a2b8c..54c0fcd0 100644 --- a/plugins/ext_test/README.md +++ b/plugins/ext_test/README.md @@ -8,12 +8,10 @@ - [Writing Tests](#writing-tests) - [License](#license) - ## Overview -This plugin supports testing of a cmd2 application by exposing access cmd2 commands with the same context -as from within a cmd2 pyscript. This allows for verification of an application's support for pyscripts. - +This plugin supports testing of a cmd2 application by exposing access cmd2 commands with the same context +as from within a cmd2 pyscript. This allows for verification of an application's support for pyscripts. ## Example cmd2 Application @@ -62,7 +60,7 @@ def example_app(): Now write your tests that validate your application using the `app_cmd` function to access the cmd2 application's commands. This allows invocation of the application's commands in the same format as a user would type. The results from calling a command matches what is returned -from running an python script with cmd2's pyscript command, which provides stdout, stderr, and +from running an python script with cmd2's pyscript command, which provides stdout, stderr, and the command's result data. ```python diff --git a/plugins/template/CHANGELOG.md b/plugins/template/CHANGELOG.md index adf951ec..c802faef 100644 --- a/plugins/template/CHANGELOG.md +++ b/plugins/template/CHANGELOG.md @@ -1,4 +1,5 @@ # Changelog + All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) @@ -7,6 +8,5 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## 1.0.0 (2018-07-24) ### Added -- Created plugin template and initial documentation - +- Created plugin template and initial documentation diff --git a/plugins/template/README.md b/plugins/template/README.md index 81e1d781..9981987f 100644 --- a/plugins/template/README.md +++ b/plugins/template/README.md @@ -10,7 +10,6 @@ - [Packaging and Distribution](#packaging-and-distribution) - [License](#license) - ## Using this template This template assumes you are creating a new cmd2 plugin called `myplugin`. Your @@ -19,13 +18,11 @@ directories in this template. Don't forget to modify the imports and `setup.py`. You'll probably also want to rewrite the README :) - ## Naming You should prefix the name of your project with `cmd2-`. Within that project, you should have a package with a prefix of `cmd2_`. - ## Adding functionality There are many ways to add functionality to `cmd2` using a plugin. Most plugins @@ -33,7 +30,6 @@ will be implemented as a mixin. A mixin is a class that encapsulates and injects code into another class. Developers who use a plugin in their `cmd2` project, will inject the plugin's code into their subclass of `cmd2.Cmd`. - ### Mixin and Initialization The following short example shows how to mix in a plugin and how the plugin @@ -75,7 +71,6 @@ required for two reasons: If you mixin the plugin after `cmd2.Cmd`, the python method resolution order will call `cmd2.Cmd` methods before it calls those in your plugin. - ### Add commands Your plugin can add user visible commands. You do it the same way in a plugin @@ -137,7 +132,6 @@ You should name your hooks so that they begin with the name of your plugin. Hook methods get mixed into the `cmd2` application and this naming convention helps avoid unintentional method overriding. - Here's a simple example: ```python @@ -163,21 +157,18 @@ See the [cmd2 hook documentation](https://cmd2.readthedocs.io/en/latest/hooks.ht for full details of the application and command lifecycle, including all available hooks and the ways hooks can influence the lifecycle. - ### Classes and Functions Your plugin can also provide classes and functions which can be used by developers of cmd2 based applications. Describe these classes and functions in your documentation so users of your plugin will know what's available. - ## Examples Include an example or two in the `examples` directory which demonstrate how your plugin works. This will help developers utilize it from within their application. - ## Development Tasks This project uses many other python modules for various development tasks, @@ -185,14 +176,16 @@ including testing, linting, building wheels, and distributing releases. These modules can be configured many different ways, which can make it difficult to learn the specific incantations required for each project you are familiar with. -This project uses [invoke]() to provide a clean, +This project uses [invoke](http://www.pyinvoke.org) to provide a clean, high level interface for these development tasks. To see the full list of functions available: + ``` $ invoke -l ``` You can run multiple tasks in a single invocation, for example: + ``` $ invoke clean docs sdist wheel ``` @@ -215,7 +208,6 @@ tiered testing strategy to accomplish this objective. This plugin template is set up to use the same strategy. - ### Create python environments This project uses [nox](https://nox.thea.codes/en/stable/) to run the test @@ -229,6 +221,7 @@ This distribution includes a shell script `build-pyenvs.sh` which automates the creation of these environments. If you prefer to create these virtualenvs by hand, do the following: + ``` $ cd cmd2_abbrev $ pyenv install 3.12 @@ -238,6 +231,7 @@ $ pyenv virtualenv -p python3.13 3.13 cmd2-3.13 ``` Now set pyenv to make both of those available at the same time: + ``` $ pyenv local cmd2-3.13 cmd2-3.13 ``` @@ -248,7 +242,7 @@ the version of python which will be executed, and the virtualenv it will utilize. | Command | python | virtualenv | -|--------------|--------|------------| +| ------------ | ------ | ---------- | | `python3.12` | 3.12 | cmd2-3.12 | | `python3.13` | 3.13 | cmd2-3.13 | | `pip3.12` | 3.12 | cmd2-3.12 | @@ -257,6 +251,7 @@ utilize. ## Install Dependencies Install all the development dependencies: + ``` $ pip install -e .[dev] ``` @@ -268,37 +263,35 @@ All the dependencies now have been installed in the `cmd2-3.13` virtualenv. If you want to work in other virtualenvs, you'll need to manually select it, and install again:: - $ pyenv shell cmd2-3.13 - $ pip install -e .[dev] +$ pyenv shell cmd2-3.13 +$ pip install -e .[dev] Now that you have your python environments created, you need to install the package in place, along with all the other development dependencies: + ``` $ pip install -e .[dev] ``` - ### Running unit tests Run `invoke pytest` from the top level directory of your plugin to run all the unit tests found in the `tests` directory. - ### Use nox to run unit tests in multiple versions of python The included `noxfile.py` is setup to run the unit tests in python 3.9 3.10, 3.11, 3.12, and 3.13 You can run your unit tests in all of these versions of python by: + ``` $ nox ``` - ### Run unit tests on multiple platforms [GitHub Actions](https://github.com/features/actions) offers free plans for open source projects - ## Packaging and Distribution When creating your `setup.py` file, keep the following in mind: @@ -309,7 +302,6 @@ When creating your `setup.py` file, keep the following in mind: doesn't try and run with a future version of `cmd2` with which it may not be compatible - ## License cmd2 [uses the very liberal MIT license](https://github.com/python-cmd2/cmd2/blob/master/LICENSE). diff --git a/tests/test_argparse.py b/tests/test_argparse.py index cca79977..61e126c0 100644 --- a/tests/test_argparse.py +++ b/tests/test_argparse.py @@ -147,6 +147,13 @@ def test_argparse_remove_quotes(argparse_app): assert out == ['hello there'] +def test_argparse_with_no_args(argparse_app): + """Make sure we receive TypeError when calling argparse-based function with no args""" + with pytest.raises(TypeError) as excinfo: + argparse_app.do_say() + assert 'Expected arguments' in str(excinfo.value) + + def test_argparser_kwargs(argparse_app, capsys): """Test with_argparser wrapper passes through kwargs to command function""" argparse_app.do_say('word', keyword_arg="foo")