Get all tokens through the one being completed, used by completion functions. :param line: the current input line with leading whitespace removed :param begidx: the beginning index of the prefix text :param endidx: the ending index of the prefix text :return: A 2 ite
(self, line: str, begidx: int, endidx: int)
| 1965 | return None |
| 1966 | |
| 1967 | def tokens_for_completion(self, line: str, begidx: int, endidx: int) -> tuple[list[str], list[str]]: |
| 1968 | """Get all tokens through the one being completed, used by completion functions. |
| 1969 | |
| 1970 | :param line: the current input line with leading whitespace removed |
| 1971 | :param begidx: the beginning index of the prefix text |
| 1972 | :param endidx: the ending index of the prefix text |
| 1973 | :return: A 2 item tuple where the items are |
| 1974 | **On Success** |
| 1975 | - tokens: list of unquoted tokens - this is generally the list needed for completion functions |
| 1976 | - raw_tokens: list of tokens with any quotes preserved = this can be used to know if a token was quoted |
| 1977 | or is missing a closing quote |
| 1978 | Both lists are guaranteed to have at least 1 item. The last item in both lists is the token being tab |
| 1979 | completed |
| 1980 | **On Failure** |
| 1981 | - Two empty lists |
| 1982 | """ |
| 1983 | unclosed_quote = "" |
| 1984 | quotes_to_try = [*constants.QUOTES] |
| 1985 | |
| 1986 | tmp_line = line[:endidx] |
| 1987 | tmp_endidx = endidx |
| 1988 | |
| 1989 | # Parse the line into tokens |
| 1990 | while True: |
| 1991 | try: |
| 1992 | initial_tokens = shlex_split(tmp_line[:tmp_endidx]) |
| 1993 | |
| 1994 | # If the cursor is at an empty token outside of a quoted string, |
| 1995 | # then that is the token being completed. Add it to the list. |
| 1996 | if not unclosed_quote and begidx == tmp_endidx: |
| 1997 | initial_tokens.append("") |
| 1998 | break |
| 1999 | except ValueError as ex: |
| 2000 | # Make sure the exception was due to an unclosed quote and |
| 2001 | # we haven't exhausted the closing quotes to try |
| 2002 | if str(ex) == "No closing quotation" and quotes_to_try: |
| 2003 | # Add a closing quote and try to parse again |
| 2004 | unclosed_quote = quotes_to_try[0] |
| 2005 | quotes_to_try = quotes_to_try[1:] |
| 2006 | |
| 2007 | tmp_line = line[:endidx] |
| 2008 | tmp_line += unclosed_quote |
| 2009 | tmp_endidx = endidx + 1 |
| 2010 | else: # pragma: no cover |
| 2011 | # The parsing error is not caused by unclosed quotes. |
| 2012 | # Return empty lists since this means the line is malformed. |
| 2013 | return [], [] |
| 2014 | |
| 2015 | # Further split tokens on punctuation characters |
| 2016 | raw_tokens = self.statement_parser.split_on_punctuation(initial_tokens) |
| 2017 | |
| 2018 | # Save the unquoted tokens |
| 2019 | tokens = [su.strip_quotes(cur_token) for cur_token in raw_tokens] |
| 2020 | |
| 2021 | # If the token being completed had an unclosed quote, we need |
| 2022 | # to remove the closing quote that was added in order for it |
| 2023 | # to match what was on the command line. |
| 2024 | if unclosed_quote: |