@@ -1321,7 +1321,7 @@ def tokens_for_completion(self, line, begidx, endidx):
13211321 On Success
13221322 tokens: list of unquoted tokens
13231323 this is generally the list needed for tab completion functions
1324- raw_tokens: list of tokens as they appear on the command line, meaning their quotes are preserved
1324+ raw_tokens: list of tokens with any quotes preserved
13251325 this can be used to know if a token was quoted or is missing a closing quote
13261326
13271327 Both lists are guaranteed to have at least 1 item
@@ -1349,7 +1349,7 @@ def tokens_for_completion(self, line, begidx, endidx):
13491349 break
13501350 except ValueError :
13511351 # ValueError can be caused by missing closing quote
1352- if len ( quotes_to_try ) == 0 :
1352+ if not quotes_to_try :
13531353 # Since we have no more quotes to try, something else
13541354 # is causing the parsing error. Return None since
13551355 # this means the line is malformed.
@@ -1481,23 +1481,23 @@ def delimiter_complete(self, text, line, begidx, endidx, match_against, delimite
14811481 matches = self .basic_complete (text , line , begidx , endidx , match_against )
14821482
14831483 # Display only the portion of the match that's being completed based on delimiter
1484- if len ( matches ) > 0 :
1484+ if matches :
14851485
14861486 # Get the common beginning for the matches
14871487 common_prefix = os .path .commonprefix (matches )
14881488 prefix_tokens = common_prefix .split (delimiter )
14891489
14901490 # Calculate what portion of the match we are completing
14911491 display_token_index = 0
1492- if len ( prefix_tokens ) > 0 :
1492+ if prefix_tokens :
14931493 display_token_index = len (prefix_tokens ) - 1
14941494
14951495 # Get this portion for each match and store them in self.display_matches
14961496 for cur_match in matches :
14971497 match_tokens = cur_match .split (delimiter )
14981498 display_token = match_tokens [display_token_index ]
14991499
1500- if len ( display_token ) == 0 :
1500+ if not display_token :
15011501 display_token = delimiter
15021502 self .display_matches .append (display_token )
15031503
@@ -1759,7 +1759,7 @@ def shell_cmd_complete(self, text, line, begidx, endidx, complete_blank=False):
17591759 :return: List[str] - a list of possible tab completions
17601760 """
17611761 # Don't tab complete anything if no shell command has been started
1762- if not complete_blank and len ( text ) == 0 :
1762+ if not complete_blank and not text :
17631763 return []
17641764
17651765 # If there are no path characters in the search text, then do shell command completion in the user's path
@@ -1862,7 +1862,7 @@ def _display_matches_gnu_readline(self, substitution, matches, longest_match_len
18621862 if rl_type == RlType .GNU :
18631863
18641864 # Check if we should show display_matches
1865- if len ( self .display_matches ) > 0 :
1865+ if self .display_matches :
18661866 matches_to_display = self .display_matches
18671867
18681868 # Recalculate longest_match_length for display_matches
@@ -1920,7 +1920,7 @@ def _display_matches_pyreadline(self, matches):
19201920 if rl_type == RlType .PYREADLINE :
19211921
19221922 # Check if we should show display_matches
1923- if len ( self .display_matches ) > 0 :
1923+ if self .display_matches :
19241924 matches_to_display = self .display_matches
19251925 else :
19261926 matches_to_display = matches
@@ -1931,117 +1931,6 @@ def _display_matches_pyreadline(self, matches):
19311931 # Display the matches
19321932 orig_pyreadline_display (matches_to_display )
19331933
1934- def _handle_completion_token_quote (self , raw_completion_token ):
1935- """
1936- This is called by complete() to add an opening quote to the token being completed if it is needed
1937- The readline input buffer is then updated with the new string
1938- :param raw_completion_token: str - the token being completed as it appears on the command line
1939- :return: True if a quote was added, False otherwise
1940- """
1941- if len (self .completion_matches ) == 0 :
1942- return False
1943-
1944- quote_added = False
1945-
1946- # Check if token on screen is already quoted
1947- if len (raw_completion_token ) == 0 or raw_completion_token [0 ] not in QUOTES :
1948-
1949- # Get the common prefix of all matches. This is what be written to the screen.
1950- common_prefix = os .path .commonprefix (self .completion_matches )
1951-
1952- # If common_prefix contains a space, then we must add an opening quote to it
1953- if ' ' in common_prefix :
1954-
1955- # Figure out what kind of quote to add
1956- if '"' in common_prefix :
1957- quote = "'"
1958- else :
1959- quote = '"'
1960-
1961- new_completion_token = quote + common_prefix
1962-
1963- # Handle a single result
1964- if len (self .completion_matches ) == 1 :
1965- str_to_append = ''
1966-
1967- # Add a closing quote if allowed
1968- if self .allow_closing_quote :
1969- str_to_append += quote
1970-
1971- orig_line = readline .get_line_buffer ()
1972- endidx = readline .get_endidx ()
1973-
1974- # If we are at the end of the line, then add a space if allowed
1975- if self .allow_appended_space and endidx == len (orig_line ):
1976- str_to_append += ' '
1977-
1978- new_completion_token += str_to_append
1979-
1980- # Update the line
1981- quote_added = True
1982- self ._replace_completion_token (raw_completion_token , new_completion_token )
1983-
1984- return quote_added
1985-
1986- def _replace_completion_token (self , raw_completion_token , new_completion_token ):
1987- """
1988- Replaces the token being completed in the readline line buffer which updates the screen
1989- This is used for things like adding an opening quote for completions with spaces
1990- :param raw_completion_token: str - the original token being completed as it appears on the command line
1991- :param new_completion_token: str- the replacement token
1992- :return: None
1993- """
1994- orig_line = readline .get_line_buffer ()
1995- endidx = readline .get_endidx ()
1996-
1997- starting_index = orig_line [:endidx ].rfind (raw_completion_token )
1998-
1999- if starting_index != - 1 :
2000- # Build the new line
2001- new_line = orig_line [:starting_index ]
2002- new_line += new_completion_token
2003- new_line += orig_line [endidx :]
2004-
2005- # Calculate the new cursor offset
2006- len_diff = len (new_completion_token ) - len (raw_completion_token )
2007- new_point = endidx + len_diff
2008-
2009- # Replace the line and update the cursor offset
2010- self ._set_readline_line (new_line )
2011- self ._set_readline_point (new_point )
2012-
2013- @staticmethod
2014- def _set_readline_line (new_line ):
2015- """
2016- Sets the readline line buffer
2017- :param new_line: str - the new line contents
2018- """
2019- if rl_type == RlType .GNU :
2020- # Byte encode the new line
2021- if six .PY3 :
2022- encoded_line = bytes (new_line , encoding = 'utf-8' )
2023- else :
2024- encoded_line = bytes (new_line )
2025-
2026- # Replace the line
2027- readline_lib .rl_replace_line (encoded_line , 0 )
2028-
2029- elif rl_type == RlType .PYREADLINE :
2030- readline .rl .mode .l_buffer .set_line (new_line )
2031-
2032- @staticmethod
2033- def _set_readline_point (new_point ):
2034- """
2035- Sets the cursor offset in the readline line buffer
2036- :param new_point: int - the new cursor offset
2037- """
2038- if rl_type == RlType .GNU :
2039- rl_point = ctypes .c_int .in_dll (readline_lib , "rl_point" )
2040- rl_point .value = new_point
2041-
2042- elif rl_type == RlType .PYREADLINE :
2043- readline .rl .mode .l_buffer .point = new_point
2044-
20451934 # ----- Methods which override stuff in cmd -----
20461935
20471936 def complete (self , text , state ):
@@ -2119,21 +2008,30 @@ def complete(self, text, state):
21192008 self .completion_matches = []
21202009 return None
21212010
2122- # readline still performs word breaks after a quote. Therefore something like quoted search
2123- # text with a space would have resulted in begidx pointing to the middle of the token we
2124- # we want to complete. Figure out where that token actually begins and save the beginning
2125- # portion of it that was not part of the text readline gave us. We will remove it from the
2126- # completions later since readline expects them to start with the original text.
2127- actual_begidx = line [:endidx ].rfind (tokens [- 1 ])
2011+ # Text we need to remove from completions later
21282012 text_to_remove = ''
21292013
2130- if actual_begidx != begidx :
2131- text_to_remove = line [ actual_begidx : begidx ]
2014+ # Get the token being completed with any opening quote preserved
2015+ raw_completion_token = raw_tokens [ - 1 ]
21322016
2133- # Adjust text and where it begins so the completer routines
2134- # get unbroken search text to complete on.
2135- text = text_to_remove + text
2136- begidx = actual_begidx
2017+ # Check if the token being completed has an opening quote
2018+ if raw_completion_token and raw_completion_token [0 ] in QUOTES :
2019+ unclosed_quote = raw_completion_token [0 ]
2020+
2021+ # readline still performs word breaks after a quote. Therefore something like quoted search
2022+ # text with a space would have resulted in begidx pointing to the middle of the token we
2023+ # we want to complete. Figure out where that token actually begins and save the beginning
2024+ # portion of it that was not part of the text readline gave us. We will remove it from the
2025+ # completions later since readline expects them to start with the original text.
2026+ actual_begidx = line [:endidx ].rfind (tokens [- 1 ])
2027+
2028+ if actual_begidx != begidx :
2029+ text_to_remove = line [actual_begidx :begidx ]
2030+
2031+ # Adjust text and where it begins so the completer routines
2032+ # get unbroken search text to complete on.
2033+ text = text_to_remove + text
2034+ begidx = actual_begidx
21372035
21382036 # Check if a valid command was entered
21392037 if command in self .get_all_commands ():
@@ -2164,7 +2062,7 @@ def complete(self, text, state):
21642062 # call the completer function for the current command
21652063 self .completion_matches = self ._redirect_complete (text , line , begidx , endidx , compfunc )
21662064
2167- if len ( self .completion_matches ) > 0 :
2065+ if self .completion_matches :
21682066
21692067 # Eliminate duplicates
21702068 matches_set = set (self .completion_matches )
@@ -2173,36 +2071,44 @@ def complete(self, text, state):
21732071 display_matches_set = set (self .display_matches )
21742072 self .display_matches = list (display_matches_set )
21752073
2176- # Get the token being completed as it appears on the command line
2177- raw_completion_token = raw_tokens [- 1 ]
2178-
2179- # Add an opening quote if needed
2180- if self ._handle_completion_token_quote (raw_completion_token ):
2181- # An opening quote was added and the screen was updated. Return no results.
2182- self .completion_matches = []
2183- return None
2184-
2185- if text_to_remove or shortcut_to_restore :
2186- # If self.display_matches is empty, then set it to self.completion_matches
2187- # before we alter them. That way the suggestions will reflect how we parsed
2188- # the token being completed and not how readline did.
2189- if len (self .display_matches ) == 0 :
2190- self .display_matches = copy .copy (self .completion_matches )
2191-
2192- # Check if we need to remove text from the beginning of tab completions
2193- if text_to_remove :
2194- self .completion_matches = \
2195- [m .replace (text_to_remove , '' , 1 ) for m in self .completion_matches ]
2196-
2197- # Check if we need to restore a shortcut in the tab completions
2198- # so it doesn't get erased from the command line
2199- if shortcut_to_restore :
2200- self .completion_matches = \
2201- [shortcut_to_restore + match for match in self .completion_matches ]
2202-
2203- # If the token being completed starts with a quote then we know it has an unclosed quote
2204- if len (raw_completion_token ) > 0 and raw_completion_token [0 ] in QUOTES :
2205- unclosed_quote = raw_completion_token [0 ]
2074+ # If self.display_matches is empty, then set it to self.completion_matches
2075+ # before we alter them. That way the suggestions will reflect how we parsed
2076+ # the token being completed and not how readline did.
2077+ if not self .display_matches :
2078+ self .display_matches = copy .copy (self .completion_matches )
2079+
2080+ # Check if we need to add an opening quote
2081+ if not unclosed_quote :
2082+
2083+ # Get the common prefix of all matches. This is the actual tab completion.
2084+ common_prefix = os .path .commonprefix (self .completion_matches )
2085+
2086+ # Join all matches into 1 string for ease of searching
2087+ all_matches_str = '' .join (self .completion_matches )
2088+
2089+ # If there is a common_prefix and any of the matches have a space,
2090+ # then we must add an opening quote to the matches.
2091+ if common_prefix and ' ' in all_matches_str :
2092+
2093+ # Figure out what kind of quote to add
2094+ if '"' in all_matches_str :
2095+ quote = "'"
2096+ else :
2097+ quote = '"'
2098+
2099+ unclosed_quote = quote
2100+ self .completion_matches = [quote + match for match in self .completion_matches ]
2101+
2102+ # Check if we need to remove text from the beginning of tab completions
2103+ elif text_to_remove :
2104+ self .completion_matches = \
2105+ [m .replace (text_to_remove , '' , 1 ) for m in self .completion_matches ]
2106+
2107+ # Check if we need to restore a shortcut in the tab completions
2108+ # so it doesn't get erased from the command line
2109+ if shortcut_to_restore :
2110+ self .completion_matches = \
2111+ [shortcut_to_restore + match for match in self .completion_matches ]
22062112
22072113 else :
22082114 # Complete token against aliases and command names
@@ -2226,7 +2132,7 @@ def complete(self, text, state):
22262132 self .completion_matches [0 ] += str_to_append
22272133
22282134 # Otherwise sort matches
2229- elif len ( self .completion_matches ) > 0 :
2135+ elif self .completion_matches :
22302136 self .completion_matches .sort ()
22312137 self .display_matches .sort ()
22322138
@@ -2871,7 +2777,7 @@ def do_alias(self, arglist):
28712777 alias save_results "print_results > out.txt"
28722778"""
28732779 # If no args were given, then print a list of current aliases
2874- if len ( arglist ) == 0 :
2780+ if not arglist :
28752781 for cur_alias in self .aliases :
28762782 self .poutput ("alias {} {}" .format (cur_alias , self .aliases [cur_alias ]))
28772783
@@ -2919,7 +2825,7 @@ def do_unalias(self, arglist):
29192825 Options:
29202826 -a remove all alias definitions
29212827"""
2922- if len ( arglist ) == 0 :
2828+ if not arglist :
29232829 self .do_help ('unalias' )
29242830
29252831 if '-a' in arglist :
@@ -3233,7 +3139,7 @@ def do_shell(self, command):
32333139
32343140 # Support expanding ~ in quoted paths
32353141 for index , _ in enumerate (tokens ):
3236- if len ( tokens [index ]) > 0 :
3142+ if tokens [index ]:
32373143 # Check if the token is quoted. Since shlex.split() passed, there isn't
32383144 # an unclosed quote, so we only need to check the first character.
32393145 first_char = tokens [index ][0 ]
0 commit comments