Skip to content

Commit 87fdda1

Browse files
authored
Merge pull request #550 from python-cmd2/macro
Added macros
2 parents bb8f6dd + 2cbc5cf commit 87fdda1

21 files changed

+1060
-321
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,3 +25,6 @@ htmlcov
2525
# mypy plugin for PyCharm
2626
dmypy.json
2727
dmypy.sock
28+
29+
# cmd2 history file used in main.py
30+
cmd2_history.txt

CHANGELOG.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,18 @@
2121
if the output is a pipe or a file the escape sequences are stripped
2222
* Always - output methods **never** strip ANSI escape sequences, regardless of the output destination
2323
* Never - output methods strip all ANSI escape sequences
24+
* Added ``macro`` command to create macros, which are similar to aliases, but can take arguments when called
25+
* ``alias`` is now an argparse command with subcommands to create, list, and delete aliases
2426
* Deprecations
25-
* Deprecated the builtin ``cmd2`` suport for colors including ``Cmd.colorize()`` and ``Cmd._colorcodes``
26-
* Deletions
27+
* Deprecated the built-in ``cmd2`` support for colors including ``Cmd.colorize()`` and ``Cmd._colorcodes``
28+
* Deletions (potentially breaking changes)
2729
* The ``preparse``, ``postparsing_precmd``, and ``postparsing_postcmd`` methods *deprecated* in the previous release
2830
have been deleted
2931
* The new application lifecycle hook system allows for registration of callbacks to be called at various points
3032
in the lifecycle and is more powerful and flexible than the previous system
33+
* ``alias`` is now a command with subcommands to create, list, and delete aliases. Therefore its syntax
34+
has changed. All current alias commands in startup scripts or transcripts will break with this release.
35+
* `unalias` was deleted since ``alias delete`` replaced it
3136

3237
## 0.9.4 (August 21, 2018)
3338
* Bug Fixes
@@ -139,7 +144,7 @@
139144
* Fixed ``AttributeError`` on Windows when running a ``select`` command cause by **pyreadline** not implementing ``remove_history_item``
140145
* Enhancements
141146
* Added warning about **libedit** variant of **readline** not being supported on macOS
142-
* Added tab-completion of alias names in value filed of **alias** command
147+
* Added tab-completion of alias names in value field of **alias** command
143148
* Enhanced the ``py`` console in the following ways
144149
* Added tab completion of Python identifiers instead of **cmd2** commands
145150
* Separated the ``py`` console history from the **cmd2** history

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ Main Features
3131
- Multi-line commands
3232
- Special-character command shortcuts (beyond cmd's `?` and `!`)
3333
- Command aliasing similar to bash `alias` command
34+
- Macros, which are similar to aliases, but can take arguments when called
3435
- Ability to load commands at startup from an initialization script
3536
- Settable environment parameters
3637
- Parsing commands with arguments using `argparse`, including support for sub-commands

cmd2/argparse_completer.py

Lines changed: 15 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -750,7 +750,7 @@ def _format_usage(self, usage, actions, groups, prefix) -> str:
750750

751751
# build full usage string
752752
format = self._format_actions_usage
753-
action_usage = format(positionals + required_options + optionals, groups)
753+
action_usage = format(required_options + optionals + positionals, groups)
754754
usage = ' '.join([s for s in [prog, action_usage] if s])
755755

756756
# wrap the usage parts if it's too long
@@ -761,15 +761,15 @@ def _format_usage(self, usage, actions, groups, prefix) -> str:
761761

762762
# break usage into wrappable parts
763763
part_regexp = r'\(.*?\)+|\[.*?\]+|\S+'
764+
req_usage = format(required_options, groups)
764765
opt_usage = format(optionals, groups)
765766
pos_usage = format(positionals, groups)
766-
req_usage = format(required_options, groups)
767+
req_parts = _re.findall(part_regexp, req_usage)
767768
opt_parts = _re.findall(part_regexp, opt_usage)
768769
pos_parts = _re.findall(part_regexp, pos_usage)
769-
req_parts = _re.findall(part_regexp, req_usage)
770+
assert ' '.join(req_parts) == req_usage
770771
assert ' '.join(opt_parts) == opt_usage
771772
assert ' '.join(pos_parts) == pos_usage
772-
assert ' '.join(req_parts) == req_usage
773773

774774
# End cmd2 customization
775775

@@ -799,13 +799,15 @@ def get_lines(parts, indent, prefix=None):
799799
if len(prefix) + len(prog) <= 0.75 * text_width:
800800
indent = ' ' * (len(prefix) + len(prog) + 1)
801801
# Begin cmd2 customization
802-
if opt_parts:
803-
lines = get_lines([prog] + pos_parts, indent, prefix)
804-
lines.extend(get_lines(req_parts, indent))
802+
if req_parts:
803+
lines = get_lines([prog] + req_parts, indent, prefix)
805804
lines.extend(get_lines(opt_parts, indent))
805+
lines.extend(get_lines(pos_parts, indent))
806+
elif opt_parts:
807+
lines = get_lines([prog] + opt_parts, indent, prefix)
808+
lines.extend(get_lines(pos_parts, indent))
806809
elif pos_parts:
807810
lines = get_lines([prog] + pos_parts, indent, prefix)
808-
lines.extend(get_lines(req_parts, indent))
809811
else:
810812
lines = [prog]
811813
# End cmd2 customization
@@ -814,13 +816,13 @@ def get_lines(parts, indent, prefix=None):
814816
else:
815817
indent = ' ' * len(prefix)
816818
# Begin cmd2 customization
817-
parts = pos_parts + req_parts + opt_parts
819+
parts = req_parts + opt_parts + pos_parts
818820
lines = get_lines(parts, indent)
819821
if len(lines) > 1:
820822
lines = []
821-
lines.extend(get_lines(pos_parts, indent))
822823
lines.extend(get_lines(req_parts, indent))
823824
lines.extend(get_lines(opt_parts, indent))
825+
lines.extend(get_lines(pos_parts, indent))
824826
# End cmd2 customization
825827
lines = [prog] + lines
826828

@@ -889,6 +891,9 @@ def _format_args(self, action, default_metavar) -> str:
889891
result = super()._format_args(action, default_metavar)
890892
return result
891893

894+
def format_help(self):
895+
return super().format_help() + '\n'
896+
892897

893898
# noinspection PyCompatibility
894899
class ACArgumentParser(argparse.ArgumentParser):

0 commit comments

Comments
 (0)