Skip to content

Commit 5635962

Browse files
committed
Fix history display issues
Issues were two fold: - HistoryItem statement.raw was getting mangled for multiline commands due to macro-related changes in _input_line_to_statement() - HistoryItem pretty printing wasn't using rstrip() anymore in verbose mode I added a couple unit tests in the process of getting here. But we should add some explicit unit tests of _input_line_to_statement() for cases like: - basic single-line command - macro single-line command - multiline command
1 parent f64f9d5 commit 5635962

File tree

5 files changed

+48
-4
lines changed

5 files changed

+48
-4
lines changed

cmd2/cmd2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1934,7 +1934,7 @@ def _input_line_to_statement(self, line: str) -> Statement:
19341934
break
19351935

19361936
# This will be true when a macro was used
1937-
if orig_line != statement.raw:
1937+
if not statement.multiline_command and orig_line != statement.raw:
19381938
# Build a Statement that contains the resolved macro line
19391939
# but the originally typed line for its raw member.
19401940
statement = Statement(statement.args,

cmd2/history.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,9 +44,9 @@ def pr(self, script=False, expanded=False, verbose=False) -> str:
4444
:return: pretty print string version of a HistoryItem
4545
"""
4646
if verbose:
47-
ret_str = self._listformat.format(self.idx, self.raw)
47+
ret_str = self._listformat.format(self.idx, self.raw.rstrip())
4848
if self.raw != self.expanded.rstrip():
49-
ret_str += self._ex_listformat.format(self.idx, self.expanded)
49+
ret_str += self._ex_listformat.format(self.idx, self.expanded.rstrip())
5050
else:
5151
if script:
5252
# display without entry numbers

examples/cmd_as_argument.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,10 @@ def __init__(self):
3131
shortcuts = dict(self.DEFAULT_SHORTCUTS)
3232
shortcuts.update({'&': 'speak'})
3333
# Set use_ipython to True to enable the "ipy" command which embeds and interactive IPython shell
34-
super().__init__(use_ipython=False, multiline_commands=['orate'], shortcuts=shortcuts)
34+
super().__init__(use_ipython=True, multiline_commands=['orate'], shortcuts=shortcuts)
3535

3636
self.allow_cli_args = False
37+
self.locals_in_py = True
3738
self.maxrepeats = 3
3839
# Make maxrepeats settable at runtime
3940
self.settable['maxrepeats'] = 'max repetitions for speak command'

tests/test_history.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010

1111
# Python 3.5 had some regressions in the unitest.mock module, so use
1212
# 3rd party mock if available
13+
from cmd2.parsing import StatementParser
14+
1315
try:
1416
import mock
1517
except ImportError:
@@ -262,6 +264,35 @@ def histitem():
262264
histitem = HistoryItem(statement, 1)
263265
return histitem
264266

267+
@pytest.fixture
268+
def parser():
269+
from cmd2.parsing import StatementParser
270+
parser = StatementParser(
271+
allow_redirection=True,
272+
terminators=[';', '&'],
273+
multiline_commands=['multiline'],
274+
aliases={'helpalias': 'help',
275+
'42': 'theanswer',
276+
'l': '!ls -al',
277+
'anothermultiline': 'multiline',
278+
'fake': 'pyscript'},
279+
shortcuts=[('?', 'help'), ('!', 'shell')]
280+
)
281+
return parser
282+
283+
def test_multiline_histitem(parser):
284+
from cmd2.history import History
285+
line = 'multiline foo\nbar\n\n'
286+
statement = parser.parse(line)
287+
history = History()
288+
history.append(statement)
289+
assert len(history) == 1
290+
hist_item = history[0]
291+
assert hist_item.raw == line
292+
pr_lines = hist_item.pr(verbose=True).splitlines()
293+
assert pr_lines[0].endswith('multiline foo')
294+
assert pr_lines[1] == 'bar'
295+
265296
def test_history_item_instantiate():
266297
from cmd2.parsing import Statement
267298
from cmd2.history import HistoryItem

tests/test_parsing.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -489,6 +489,18 @@ def test_parse_unfinished_multiliine_command(parser):
489489
assert statement.arg_list == statement.argv[1:]
490490
assert statement.terminator == ''
491491

492+
def test_parse_basic_multiline_command(parser):
493+
line = 'multiline foo\nbar\n\n'
494+
statement = parser.parse(line)
495+
assert statement.multiline_command == 'multiline'
496+
assert statement.command == 'multiline'
497+
assert statement == 'foo bar'
498+
assert statement.args == statement
499+
assert statement.argv == ['multiline', 'foo', 'bar']
500+
assert statement.arg_list == ['foo', 'bar']
501+
assert statement.raw == line
502+
assert statement.terminator == '\n'
503+
492504
@pytest.mark.parametrize('line,terminator',[
493505
('multiline has > inside;', ';'),
494506
('multiline has > inside;;;', ';'),

0 commit comments

Comments
 (0)