summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd Leonhardt <todd.leonhardt@gmail.com>2018-06-07 17:14:54 -0700
committerGitHub <noreply@github.com>2018-06-07 17:14:54 -0700
commitfd60e40bf96e06ff9410f71acbadfb43e3527dfd (patch)
tree4feb462ba0ca571b6c24427dd7d1b7f5554ddd71
parenteb8181e7d3f900cecd1455efd75f3b5c5f6918cd (diff)
parent5aa4eb17954f046a284fb2a81d5d5abd6adc11df (diff)
downloadcmd2-git-fd60e40bf96e06ff9410f71acbadfb43e3527dfd.tar.gz
Merge pull request #434 from python-cmd2/fix_redirection
Fix unexpected redirection behavior
-rw-r--r--cmd2/cmd2.py18
-rw-r--r--cmd2/parsing.py24
2 files changed, 30 insertions, 12 deletions
diff --git a/cmd2/cmd2.py b/cmd2/cmd2.py
index bb4ac4ad..d0d8352c 100644
--- a/cmd2/cmd2.py
+++ b/cmd2/cmd2.py
@@ -33,7 +33,6 @@ import argparse
import cmd
import collections
from colorama import Fore
-import copy
import glob
import os
import platform
@@ -498,10 +497,11 @@ class Cmd(cmd.Cmd):
# An optional header that prints above the tab-completion suggestions
self.completion_header = ''
- # If the tab-completion suggestions should be displayed in a way that is different than the actual match values,
- # then place those results in this list. The full matches still must be returned from your completer function.
- # For an example, look at path_complete() which uses this to show only the basename of paths as the
- # suggestions. delimiter_complete() also populates this list.
+ # Use this list if you are completing strings that contain a common delimiter and you only want to
+ # display the final portion of the matches as the tab-completion suggestions. The full matches
+ # still must be returned from your completer function. For an example, look at path_complete()
+ # which uses this to show only the basename of paths as the suggestions. delimiter_complete() also
+ # populates this list.
self.display_matches = []
# Used by functions like path_complete() and delimiter_complete() to properly
@@ -692,6 +692,7 @@ class Cmd(cmd.Cmd):
On Failure
Both items are None
"""
+ import copy
unclosed_quote = ''
quotes_to_try = copy.copy(constants.QUOTES)
@@ -1330,7 +1331,7 @@ class Cmd(cmd.Cmd):
# from text and update the indexes. This only applies if we are at the the beginning of the line.
shortcut_to_restore = ''
if begidx == 0:
- for (shortcut, expansion) in self.shortcuts:
+ for (shortcut, _) in self.shortcuts:
if text.startswith(shortcut):
# Save the shortcut to restore later
shortcut_to_restore = shortcut
@@ -1439,6 +1440,7 @@ class Cmd(cmd.Cmd):
# Since self.display_matches is empty, set it to self.completion_matches
# before we alter them. That way the suggestions will reflect how we parsed
# the token being completed and not how readline did.
+ import copy
self.display_matches = copy.copy(self.completion_matches)
# Check if we need to add an opening quote
@@ -1855,7 +1857,7 @@ class Cmd(cmd.Cmd):
if statement.output == constants.REDIRECTION_APPEND:
mode = 'a'
try:
- sys.stdout = self.stdout = open(os.path.expanduser(statement.output_to), mode)
+ sys.stdout = self.stdout = open(statement.output_to, mode)
except OSError as ex:
self.perror('Not Redirecting because - {}'.format(ex), traceback_war=False)
self.redirecting = False
@@ -2384,7 +2386,7 @@ Usage: Usage: unalias [-a] name [name ...]
fulloptions.append((opt[0], opt[1]))
except IndexError:
fulloptions.append((opt[0], opt[0]))
- for (idx, (value, text)) in enumerate(fulloptions):
+ for (idx, (_, text)) in enumerate(fulloptions):
self.poutput(' %2d. %s\n' % (idx + 1, text))
while True:
response = input(prompt)
diff --git a/cmd2/parsing.py b/cmd2/parsing.py
index 655e0c58..8d59aedb 100644
--- a/cmd2/parsing.py
+++ b/cmd2/parsing.py
@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*-
"""Statement parsing classes for cmd2"""
+import os
import re
import shlex
from typing import List, Tuple
@@ -38,7 +39,7 @@ class Statement(str):
from the elements of the list, and aliases and shortcuts
are expanded
:type argv: list
- :var terminator: the charater which terminated the multiline command, if
+ :var terminator: the character which terminated the multiline command, if
there was one
:type terminator: str or None
:var suffix: characters appearing after the terminator but before output
@@ -49,7 +50,7 @@ class Statement(str):
:type pipe_to: list
:var output: if output was redirected, the redirection token, i.e. '>>'
:type output: str or None
- :var output_to: if output was redirected, the destination, usually a filename
+ :var output_to: if output was redirected, the destination file
:type output_to: str or None
"""
@@ -297,6 +298,11 @@ class StatementParser:
pipe_pos = tokens.index(constants.REDIRECTION_PIPE)
# save everything after the first pipe as tokens
pipe_to = tokens[pipe_pos+1:]
+
+ for pos, cur_token in enumerate(pipe_to):
+ unquoted_token = utils.strip_quotes(cur_token)
+ pipe_to[pos] = os.path.expanduser(unquoted_token)
+
# remove all the tokens after the pipe
tokens = tokens[:pipe_pos]
except ValueError:
@@ -309,7 +315,12 @@ class StatementParser:
try:
output_pos = tokens.index(constants.REDIRECTION_OUTPUT)
output = constants.REDIRECTION_OUTPUT
- output_to = ' '.join(tokens[output_pos+1:])
+
+ # Check if we are redirecting to a file
+ if len(tokens) > output_pos + 1:
+ unquoted_path = utils.strip_quotes(tokens[output_pos + 1])
+ output_to = os.path.expanduser(unquoted_path)
+
# remove all the tokens after the output redirect
tokens = tokens[:output_pos]
except ValueError:
@@ -318,7 +329,12 @@ class StatementParser:
try:
output_pos = tokens.index(constants.REDIRECTION_APPEND)
output = constants.REDIRECTION_APPEND
- output_to = ' '.join(tokens[output_pos+1:])
+
+ # Check if we are redirecting to a file
+ if len(tokens) > output_pos + 1:
+ unquoted_path = utils.strip_quotes(tokens[output_pos + 1])
+ output_to = os.path.expanduser(unquoted_path)
+
# remove all tokens after the output redirect
tokens = tokens[:output_pos]
except ValueError: