Skip to content

Commit 78e239e

Browse files
committed
Optimized Statement class.
- Made Statement.arg_list a property which generates the list on-demand. - Renamed Statement.output to Statement.redirector. - Renamed Statement.output_to to Statement.redirect_to. - Removed Statement.pipe_to since it's data can be stored in Statement.redirector and Statement.redirect_to.
1 parent 09b2998 commit 78e239e

File tree

6 files changed

+297
-355
lines changed

6 files changed

+297
-355
lines changed

cmd2/cmd2.py

Lines changed: 22 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -595,7 +595,7 @@ def _(event: Any) -> None: # pragma: no cover
595595
if os.path.exists(startup_script):
596596
script_cmd = f"run_script {su.quote(startup_script)}"
597597
if silence_startup_script:
598-
script_cmd += f" {constants.REDIRECTION_OUTPUT} {os.devnull}"
598+
script_cmd += f" {constants.REDIRECTION_OVERWRITE} {os.devnull}"
599599
self._startup_commands.append(script_cmd)
600600

601601
# Transcript files to run instead of interactive command loop
@@ -2140,7 +2140,7 @@ def _redirect_complete(self, text: str, line: str, begidx: int, endidx: int, com
21402140

21412141
if prior_token == constants.REDIRECTION_PIPE:
21422142
do_shell_completion = True
2143-
elif in_pipe or prior_token in (constants.REDIRECTION_OUTPUT, constants.REDIRECTION_APPEND):
2143+
elif in_pipe or prior_token in (constants.REDIRECTION_OVERWRITE, constants.REDIRECTION_APPEND):
21442144
do_path_completion = True
21452145

21462146
prior_token = cur_token
@@ -2190,14 +2190,14 @@ def _perform_completion(
21902190
# Parse the command line to get the command token.
21912191
command = ''
21922192
if custom_settings is None:
2193-
statement = self.statement_parser.parse_command_only(line)
2194-
command = statement.command
2193+
partial_statement = self.statement_parser.parse_command_only(line)
2194+
command = partial_statement.command
21952195

21962196
# Malformed command line (e.g. quoted command token)
21972197
if not command:
21982198
return Completions()
21992199

2200-
expanded_line = statement.command_and_args
2200+
expanded_line = partial_statement.command_and_args
22012201

22022202
if not expanded_line[-1:].isspace():
22032203
# Unquoted trailing whitespace gets stripped by parse_command_only().
@@ -2642,8 +2642,8 @@ def parseline(self, line: str) -> tuple[str, str, str]:
26422642
:param line: line read by prompt-toolkit
26432643
:return: tuple containing (command, args, line)
26442644
"""
2645-
statement = self.statement_parser.parse_command_only(line)
2646-
return statement.command, statement.args, statement.command_and_args
2645+
partial_statement = self.statement_parser.parse_command_only(line)
2646+
return partial_statement.command, partial_statement.args, partial_statement.command_and_args
26472647

26482648
def onecmd_plus_hooks(
26492649
self,
@@ -2853,8 +2853,8 @@ def _complete_statement(self, line: str) -> Statement:
28532853
except Cmd2ShlexError:
28542854
# we have an unclosed quotation mark, let's parse only the command
28552855
# and see if it's a multiline
2856-
statement = self.statement_parser.parse_command_only(line)
2857-
if not statement.multiline_command:
2856+
partial_statement = self.statement_parser.parse_command_only(line)
2857+
if not partial_statement.multiline_command:
28582858
# not a multiline command, so raise the exception
28592859
raise
28602860

@@ -2929,13 +2929,11 @@ def _input_line_to_statement(self, line: str) -> Statement:
29292929
statement.args,
29302930
raw=orig_line,
29312931
command=statement.command,
2932-
arg_list=statement.arg_list,
29332932
multiline_command=statement.multiline_command,
29342933
terminator=statement.terminator,
29352934
suffix=statement.suffix,
2936-
pipe_to=statement.pipe_to,
2937-
output=statement.output,
2938-
output_to=statement.output_to,
2935+
redirector=statement.redirector,
2936+
redirect_to=statement.redirect_to,
29392937
)
29402938
return statement
29412939

@@ -3003,7 +3001,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
30033001
# Don't return since we set some state variables at the end of the function
30043002
pass
30053003

3006-
elif statement.pipe_to:
3004+
elif statement.redirector == constants.REDIRECTION_PIPE:
30073005
# Create a pipe with read and write sides
30083006
read_fd, write_fd = os.pipe()
30093007

@@ -3027,7 +3025,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
30273025

30283026
# For any stream that is a StdSim, we will use a pipe so we can capture its output
30293027
proc = subprocess.Popen( # noqa: S602
3030-
statement.pipe_to,
3028+
statement.redirect_to,
30313029
stdin=subproc_stdin,
30323030
stdout=subprocess.PIPE if isinstance(self.stdout, utils.StdSim) else self.stdout, # type: ignore[unreachable]
30333031
stderr=subprocess.PIPE if isinstance(sys.stderr, utils.StdSim) else sys.stderr,
@@ -3054,14 +3052,14 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
30543052
if stdouts_match:
30553053
sys.stdout = self.stdout
30563054

3057-
elif statement.output:
3058-
if statement.output_to:
3055+
elif statement.redirector in (constants.REDIRECTION_OVERWRITE, constants.REDIRECTION_APPEND):
3056+
if statement.redirect_to:
30593057
# redirecting to a file
30603058
# statement.output can only contain REDIRECTION_APPEND or REDIRECTION_OUTPUT
3061-
mode = 'a' if statement.output == constants.REDIRECTION_APPEND else 'w'
3059+
mode = 'a' if statement.redirector == constants.REDIRECTION_APPEND else 'w'
30623060
try:
30633061
# Use line buffering
3064-
new_stdout = cast(TextIO, open(su.strip_quotes(statement.output_to), mode=mode, buffering=1)) # noqa: SIM115
3062+
new_stdout = cast(TextIO, open(su.strip_quotes(statement.redirect_to), mode=mode, buffering=1)) # noqa: SIM115
30653063
except OSError as ex:
30663064
raise RedirectionError('Failed to redirect output') from ex
30673065

@@ -3092,7 +3090,7 @@ def _redirect_output(self, statement: Statement) -> utils.RedirectionSavedState:
30923090
if stdouts_match:
30933091
sys.stdout = self.stdout
30943092

3095-
if statement.output == constants.REDIRECTION_APPEND:
3093+
if statement.redirector == constants.REDIRECTION_APPEND:
30963094
self.stdout.write(current_paste_buffer)
30973095
self.stdout.flush()
30983096

@@ -3110,7 +3108,10 @@ def _restore_output(self, statement: Statement, saved_redir_state: utils.Redirec
31103108
"""
31113109
if saved_redir_state.redirecting:
31123110
# If we redirected output to the clipboard
3113-
if statement.output and not statement.output_to:
3111+
if (
3112+
statement.redirector in (constants.REDIRECTION_OVERWRITE, constants.REDIRECTION_APPEND)
3113+
and not statement.redirect_to
3114+
):
31143115
self.stdout.seek(0)
31153116
write_to_paste_buffer(self.stdout.read())
31163117

cmd2/constants.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,10 @@
88
# Used for command parsing, output redirection, completion, and word breaks. Do not change.
99
QUOTES = ['"', "'"]
1010
REDIRECTION_PIPE = '|'
11-
REDIRECTION_OUTPUT = '>'
11+
REDIRECTION_OVERWRITE = '>'
1212
REDIRECTION_APPEND = '>>'
13-
REDIRECTION_CHARS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT]
14-
REDIRECTION_TOKENS = [REDIRECTION_PIPE, REDIRECTION_OUTPUT, REDIRECTION_APPEND]
13+
REDIRECTION_CHARS = [REDIRECTION_PIPE, REDIRECTION_OVERWRITE]
14+
REDIRECTION_TOKENS = [REDIRECTION_PIPE, REDIRECTION_OVERWRITE, REDIRECTION_APPEND]
1515
COMMENT_CHAR = '#'
1616
MULTILINE_TERMINATOR = ';'
1717

cmd2/history.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ class to gain access to the historical record.
146146
"""
147147

148148
# Used in JSON dictionaries
149-
_history_version = '1.0.0'
149+
_history_version = '4.0.0'
150150
_history_version_field = 'history_version'
151151
_history_items_field = 'history_items'
152152

0 commit comments

Comments
 (0)