From 64b3a88f2376820ae0af2efeace6d63115fb4891 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sat, 20 May 2017 00:06:22 -0700 Subject: [PATCH 1/2] Abbreviations are no longer accepted for multiline commands Due to the way the parsing logic works for multiline commands, abbreviations didn't function properly with mutliline commands. So to avoid confusion, this commit deals with this issue by simply disallowing abbreviations for multiline commands altogether. A warning has been added to the section on abbreviations in the documentation to hopefully make this clear for users. --- cmd2.py | 4 ++-- docs/freefeatures.rst | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd2.py b/cmd2.py index 1de93ec23..142033673 100755 --- a/cmd2.py +++ b/cmd2.py @@ -600,7 +600,7 @@ class Cmd(cmd.Cmd): excludeFromHistory = '''run r list l history hi ed edit li eof'''.split() # make sure your terminators are not in legalChars! legalChars = u'!#$%.:?@_-' + pyparsing.alphanums + pyparsing.alphas8bit - multilineCommands = [] + multilineCommands = [] # NOTE: Multiline commands can never be abbreviated, even if abbrev is True noSpecialParse = 'set ed edit exit'.split() prefixParser = pyparsing.Empty() redirector = '>' # for sending output to file @@ -1089,7 +1089,7 @@ def func_named(self, arg): result = target else: if self.abbrev: # accept shortened versions of commands - funcs = [fname for fname in self.keywords if fname.startswith(arg)] + funcs = [func for func in self.keywords if func.startswith(arg) and func not in self.multilineCommands] if len(funcs) == 1: result = 'do_' + funcs[0] return result diff --git a/docs/freefeatures.rst b/docs/freefeatures.rst index 44ade4083..3c740c00b 100644 --- a/docs/freefeatures.rst +++ b/docs/freefeatures.rst @@ -243,6 +243,11 @@ no other commands defined beginning with *divid*, This behavior can be turned off with ``app.abbrev`` (see :ref:`parameters`) +.. warning:: + + Due to the way the parsing logic works for multiline commands, abbreviations + will not be accepted for multiline commands. + Misc. pre-defined commands ========================== From a57c664511a42eeeafa530d185f5ff89c6060496 Mon Sep 17 00:00:00 2001 From: Todd Leonhardt Date: Sun, 21 May 2017 16:54:03 -0700 Subject: [PATCH 2/2] Added a unit test and updated changes --- CHANGES.md | 1 + tests/test_parsing.py | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index b71172158..83af7d37d 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -23,6 +23,7 @@ News * 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 ----- diff --git a/tests/test_parsing.py b/tests/test_parsing.py index d6b64093e..171f33a5c 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -2,7 +2,7 @@ """ Unit/functional testing for helper functions/classes in the cmd2.py module. -These are primarily tests related to parsing. Moreover, they are mostly a port of the old doctest tests which were +These are primarily tests related to parsing. Moreover, they are mostly a port of the old doctest tests which were problematic because they worked properly for some versions of pyparsing but not for others. Copyright 2017 Todd Leonhardt @@ -247,6 +247,12 @@ def test_parse_multiline_ignores_terminators_in_comments(parser): assert results.terminator[0] == '\n' assert results.terminator[1] == '\n' +def test_parse_abbreviated_multiline_not_allowed(parser): + line = 'multilin command\n' + results = parser.parseString(line) + assert results.command == 'multilin' + assert results.multilineCommand == '' + # Unicode support is only present in cmd2 for Python 3 @pytest.mark.skipif(sys.version_info < (3,0), reason="cmd2 unicode support requires python3") def test_parse_command_with_unicode_args(parser):