Skip to content

Commit c4ee214

Browse files
committed
Preserving originally typed quotes of Statement.output_to for use in Statement.post_command()
1 parent 8ad8ddd commit c4ee214

File tree

3 files changed

+29
-19
lines changed

3 files changed

+29
-19
lines changed

cmd2/cmd2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2082,7 +2082,7 @@ def _redirect_output(self, statement: Statement) -> Tuple[bool, utils.Redirectio
20822082
if statement.output == constants.REDIRECTION_APPEND:
20832083
mode = 'a'
20842084
try:
2085-
new_stdout = open(statement.output_to, mode)
2085+
new_stdout = open(utils.strip_quotes(statement.output_to), mode)
20862086
saved_state.redirecting = True
20872087
sys.stdout = self.stdout = new_stdout
20882088
except OSError as ex:

cmd2/parsing.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
# -*- coding: utf-8 -*-
33
"""Statement parsing classes for cmd2"""
44

5-
import os
65
import re
76
import shlex
87
from typing import Dict, Iterable, List, Optional, Tuple, Union
@@ -166,7 +165,7 @@ def do_mycommand(stmt):
166165
# if output was redirected, the redirection token, i.e. '>>'
167166
output = attr.ib(default='', validator=attr.validators.instance_of(str))
168167

169-
# if output was redirected, the destination file
168+
# if output was redirected, the destination file token (quotes preserved)
170169
output_to = attr.ib(default='', validator=attr.validators.instance_of(str))
171170

172171
def __new__(cls, value: object, *pos_args, **kw_args):
@@ -213,7 +212,7 @@ def post_command(self) -> str:
213212
if self.output:
214213
rtn += ' ' + self.output
215214
if self.output_to:
216-
rtn += ' ' + utils.quote_string_if_needed(self.output_to)
215+
rtn += ' ' + self.output_to
217216

218217
return rtn
219218

@@ -495,9 +494,11 @@ def parse(self, line: str, expand: bool = True) -> Statement:
495494
output = constants.REDIRECTION_APPEND
496495
output_index = append_index
497496

497+
# Check if we are redirecting to a file
498498
if len(tokens) > output_index + 1:
499499
unquoted_path = utils.strip_quotes(tokens[output_index + 1])
500-
output_to = os.path.expanduser(unquoted_path)
500+
if unquoted_path:
501+
output_to = utils.expand_user(tokens[output_index + 1])
501502

502503
# remove all the tokens after the output redirect
503504
tokens = tokens[:output_index]

cmd2/utils.py

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -275,25 +275,34 @@ def unquote_specific_tokens(args: List[str], tokens_to_unquote: List[str]) -> No
275275
args[i] = unquoted_arg
276276

277277

278+
def expand_user(token: str) -> str:
279+
"""
280+
Wrap os.expanduser() to support expanding ~ in quoted strings
281+
:param token: the string to expand
282+
"""
283+
if token:
284+
if is_quoted(token):
285+
quote_char = token[0]
286+
token = strip_quotes(token)
287+
else:
288+
quote_char = ''
289+
290+
token = os.path.expanduser(token)
291+
292+
# Restore the quotes even if not needed to preserve what the user typed
293+
if quote_char:
294+
token = quote_char + token + quote_char
295+
296+
return token
297+
298+
278299
def expand_user_in_tokens(tokens: List[str]) -> None:
279300
"""
280-
Call os.path.expanduser() on all tokens in an already parsed list of command-line arguments.
281-
This also supports expanding user in quoted tokens.
301+
Call expand_user() on all tokens in a list of strings
282302
:param tokens: tokens to expand
283303
"""
284304
for index, _ in enumerate(tokens):
285-
if tokens[index]:
286-
# Check if the token is quoted. Since parsing already passed, there isn't
287-
# an unclosed quote. So we only need to check the first character.
288-
first_char = tokens[index][0]
289-
if first_char in constants.QUOTES:
290-
tokens[index] = strip_quotes(tokens[index])
291-
292-
tokens[index] = os.path.expanduser(tokens[index])
293-
294-
# Restore the quotes even if not needed to preserve what the user typed
295-
if first_char in constants.QUOTES:
296-
tokens[index] = first_char + tokens[index] + first_char
305+
tokens[index] = expand_user(tokens[index])
297306

298307

299308
def find_editor() -> str:

0 commit comments

Comments
 (0)