summaryrefslogtreecommitdiff
path: root/cmd2.py
diff options
context:
space:
mode:
authorKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-20 01:48:04 -0400
committerKevin Van Brunt <kmvanbrunt@gmail.com>2018-03-20 01:48:04 -0400
commit2a3c79231521409984318c22b28150e232a0b637 (patch)
tree2e064fc9fcebe806a8aa56b6acde9f092c1bba3a /cmd2.py
parentbc28141b791b7d524e610db3d09b1b3266f2fc41 (diff)
downloadcmd2-git-2a3c79231521409984318c22b28150e232a0b637.tar.gz
Automatically adding an opening quote if needed during tab completion
Diffstat (limited to 'cmd2.py')
-rw-r--r--cmd2.py149
1 files changed, 84 insertions, 65 deletions
diff --git a/cmd2.py b/cmd2.py
index 4e3fdfd8..92a3c043 100644
--- a/cmd2.py
+++ b/cmd2.py
@@ -1491,27 +1491,6 @@ class Cmd(cmd.Cmd):
# If begidx is greater than 0, then the cursor is past the command
if begidx > 0:
- # Get all tokens through the one being completed
- tokens = tokens_for_completion(line, begidx, endidx, preserve_quotes=True)
-
- # Check if the token being complete has an unclosed quote
- quotes = ['"', "'"]
- token_being_completed = tokens[-1]
- unclosed_quote = ''
-
- if len(token_being_completed) > 1:
- first_char = token_being_completed[0]
- last_char = token_being_completed[-1]
-
- if first_char in quotes and first_char != last_char:
- unclosed_quote = first_char
-
- # If the cursor is right after a closed quote, then insert a space
- prior_char = line[begidx - 1]
- if not unclosed_quote and prior_char in quotes:
- self.completion_matches = [' ']
- return self.completion_matches[state]
-
# Parse the command line
command, args, expanded_line = self.parseline(line)
@@ -1530,6 +1509,29 @@ class Cmd(cmd.Cmd):
# Overwrite line to pass into completers
line = expanded_line
+ # Get all tokens through the one being completed
+ tokens = tokens_for_completion(line, begidx, endidx, preserve_quotes=True)
+
+ # Get the status of quotes in the token being completed
+ quotes = ['"', "'"]
+ token_being_completed = tokens[-1]
+ unclosed_quote = ''
+
+ if len(token_being_completed) > 1:
+ first_char = token_being_completed[0]
+ last_char = token_being_completed[-1]
+
+ # Check if the token being completed has an unclosed quote
+ if first_char in quotes and first_char != last_char:
+ unclosed_quote = first_char
+
+ # If the cursor is right after a closed quote, then insert a space
+ else:
+ prior_char = line[begidx - 1]
+ if not unclosed_quote and prior_char in quotes:
+ self.completion_matches = [' ']
+ return self.completion_matches[state]
+
# Otherwise select a completer function
if command == '':
compfunc = self.completedefault
@@ -1557,50 +1559,67 @@ class Cmd(cmd.Cmd):
self.completion_matches = compfunc(text, line, begidx, endidx)
# Check if we need to add an opening quote
- if len(self.completion_matches) > 0:
- first_char = token_being_completed[0]
-
- if first_char not in quotes:
- # Get the common prefix of all matches. This is what is added to the token being completed.
- common_prefix = os.path.commonprefix(self.completion_matches)
-
- # If anything that will be in the token being completed contains a space, then
- # we must add an opening quote to the token on screen
- if ' ' in token_being_completed or ' ' in common_prefix:
- # Find in the original line on screen where our token starts
- starting_index = 0
- for token_index, cur_token in enumerate(tokens):
- starting_index = origline.find(cur_token)
- if token_index < len(tokens) - 1:
- starting_index += len(cur_token)
-
- # If the token started at begidx, then all we have to do is prepend
- # an opening quote to all the completions. Readline will do the rest.
- if starting_index == readline.get_begidx():
- self.completion_matches = ['"' + match for match in self.completion_matches]
-
- # The token started after begidx, therefore we need to manually insert an
- # opening quote before the token in the readline buffer.
- else:
- # GNU readline specific way to insert an opening quote
- if readline_lib:
- # Get and save the current cursor position
- rl_point = ctypes.c_int.in_dll(readline_lib, "rl_point")
- orig_rl_point = rl_point.value
-
- # Move the cursor where the token being completed begins to insert the opening quote
- rl_point.value = starting_index
- readline.insert_text('"')
-
- # Restore the cursor 1 past where it was the since we shifted everything
- rl_point.value = orig_rl_point + 1
-
- # Since we just shifted the whole command line over by one, readline will begin
- # inserting the text one spot to the left of where we want it since it still is
- # using the original index. Therefore we must prepend the original character that
- # is 1 spot before where text begins to make sure it doesn't get erased.
- saved_char = token_being_completed[(len(text) + 1) * -1]
- self.completion_matches = [saved_char + match for match in self.completion_matches]
+ if len(self.completion_matches) > 0 and \
+ (len(token_being_completed) == 0 or token_being_completed[0] not in quotes):
+ # Get the common prefix of all matches. This is what is added to the token being completed.
+ common_prefix = os.path.commonprefix(self.completion_matches)
+
+ # If anything that will be in the token being completed contains a space, then
+ # we must add an opening quote to the token on screen
+ if ' ' in token_being_completed or ' ' in common_prefix:
+
+ # Mark that there is now an unclosed quote
+ unclosed_quote = '"'
+
+ # Find in the original line on screen where our token starts
+ starting_index = 0
+ for token_index, cur_token in enumerate(tokens):
+ starting_index = origline.find(cur_token)
+ if token_index < len(tokens) - 1:
+ starting_index += len(cur_token)
+
+ # If the token started at begidx, then all we have to do is prepend
+ # an opening quote to all the completions. Readline will do the rest.
+ if starting_index == readline.get_begidx():
+ self.completion_matches = ['"' + match for match in self.completion_matches]
+
+ # The token started after begidx, therefore we need to manually insert an
+ # opening quote before the token in the readline buffer.
+ else:
+ # GNU readline specific way to insert an opening quote
+ if readline_lib:
+ # Get and save the current cursor position
+ rl_point = ctypes.c_int.in_dll(readline_lib, "rl_point")
+ orig_rl_point = rl_point.value
+
+ # Move the cursor where the token being completed begins to insert the opening quote
+ rl_point.value = starting_index
+ readline.insert_text('"')
+
+ # Restore the cursor 1 past where it was the since we shifted everything
+ rl_point.value = orig_rl_point + 1
+
+ # Since we just shifted the whole command line over by one, readline will begin
+ # inserting the text one spot to the left of where we want it since it still has
+ # the original values of begidx and endidx and we can't change them. Therefore we must
+ # prepend to every match the character right before the text variable so it doesn't
+ # get erased.
+ saved_char = token_being_completed[(len(text) + 1) * -1]
+ self.completion_matches = [saved_char + match for match in self.completion_matches]
+
+ # pyreadline specific way to insert an opening quote
+ elif sys.platform.startswith('win'):
+ # Save the current cursor position
+ orig_rl_point = readline.rl.mode.l_buffer.point
+
+ # Move the cursor where the token being completed begins to insert the opening quote
+ readline.rl.mode.l_buffer.point = starting_index
+ readline.insert_text('"')
+
+ # Shift the cursor and completion indexes by 1 to account for the added quote
+ readline.rl.mode.l_buffer.point = orig_rl_point + 1
+ readline.rl.mode.begidx += 1
+ readline.rl.mode.endidx += 1
# Handle single result
if len(self.completion_matches) == 1: