Skip to content

Commit fb4e0c2

Browse files
committed
Refactor parseline() for #380
1 parent be847c1 commit fb4e0c2

File tree

2 files changed

+22
-54
lines changed

2 files changed

+22
-54
lines changed

cmd2/cmd2.py

Lines changed: 4 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1921,66 +1921,16 @@ def postparsing_postcmd(self, stop: bool) -> bool:
19211921
def parseline(self, line):
19221922
"""Parse the line into a command name and a string containing the arguments.
19231923
1924-
NOTE: This is an override of a parent class method. It is only used by other parent class methods. But
1925-
we do need to override it here so that the additional shortcuts present in cmd2 get properly expanded for
1926-
purposes of tab completion.
1924+
NOTE: This is an override of a parent class method. It is only used by other parent class methods.
19271925
1928-
Used for command tab completion. Returns a tuple containing (command, args, line).
1929-
'command' and 'args' may be None if the line couldn't be parsed.
1926+
Different from the parent class method, this ignores self.identchars.
19301927
19311928
:param line: str - line read by readline
19321929
:return: (str, str, str) - tuple containing (command, args, line)
19331930
"""
1934-
line = line.strip()
19351931

1936-
if not line:
1937-
# Deal with empty line or all whitespace line
1938-
return None, None, line
1939-
1940-
# Make a copy of aliases so we can edit it
1941-
tmp_aliases = list(self.aliases.keys())
1942-
keep_expanding = len(tmp_aliases) > 0
1943-
1944-
# Expand aliases
1945-
while keep_expanding:
1946-
for cur_alias in tmp_aliases:
1947-
keep_expanding = False
1948-
1949-
if line == cur_alias or line.startswith(cur_alias + ' '):
1950-
line = line.replace(cur_alias, self.aliases[cur_alias], 1)
1951-
1952-
# Do not expand the same alias more than once
1953-
tmp_aliases.remove(cur_alias)
1954-
keep_expanding = len(tmp_aliases) > 0
1955-
break
1956-
1957-
# Expand command shortcut to its full command name
1958-
for (shortcut, expansion) in self.shortcuts:
1959-
if line.startswith(shortcut):
1960-
# If the next character after the shortcut isn't a space, then insert one
1961-
shortcut_len = len(shortcut)
1962-
if len(line) == shortcut_len or line[shortcut_len] != ' ':
1963-
expansion += ' '
1964-
1965-
# Expand the shortcut
1966-
line = line.replace(shortcut, expansion, 1)
1967-
break
1968-
1969-
i, n = 0, len(line)
1970-
1971-
# If we are allowing shell commands, then allow any character in the command
1972-
if self.default_to_shell:
1973-
while i < n and line[i] != ' ':
1974-
i += 1
1975-
1976-
# Otherwise only allow those in identchars
1977-
else:
1978-
while i < n and line[i] in self.identchars:
1979-
i += 1
1980-
1981-
command, arg = line[:i], line[i:].strip()
1982-
1983-
return command, arg, line
1932+
statement = self.statement_parser.parse_command_only(line)
1933+
return statement.command, statement.args, statement.command_and_args
19841934

19851935
def onecmd_plus_hooks(self, line):
19861936
"""Top-level function called by cmdloop() to handle parsing a line and running the command and all of its hooks.

tests/test_cmd2.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1718,3 +1718,21 @@ def test_ppaged(base_app):
17181718
base_app.ppaged(msg)
17191719
out = base_app.stdout.buffer
17201720
assert out == msg + end
1721+
1722+
# we override cmd.parseline() so we always get consistent
1723+
# command parsing by parent methods we don't override
1724+
# don't need to test all the parsing logic here, because
1725+
# parseline just calls StatementParser.parse_command_only()
1726+
def test_parseline_empty(base_app):
1727+
statement = ''
1728+
command, args, line = base_app.parseline(statement)
1729+
assert not command
1730+
assert not args
1731+
assert not line
1732+
1733+
def test_parseline(base_app):
1734+
statement = " command with 'partially completed quotes "
1735+
command, args, line = base_app.parseline(statement)
1736+
assert command == 'command'
1737+
assert args == "with 'partially completed quotes"
1738+
assert line == statement.strip()

0 commit comments

Comments
 (0)