def test_split(self): """Test splitting.""" for case in test_data.strip().splitlines(): cmd, out = case.split('/')[:-2] with self.subTest(cmd=cmd): items = split.split(cmd) self.assertEqual(items, out.split('|'))
def test_split_keep(self): """Test splitting with keep=True.""" for case in test_data.strip().splitlines(): cmd, _mid, out = case.split('/')[:-1] with self.subTest(cmd=cmd): items = split.split(cmd, keep=True) self.assertEqual(items, out.split('|'))
def test_split_keep_original(self): """Test if splitting with keep=True yields the original string.""" for case in test_data.strip().splitlines(): cmd = case.split('/')[0] with self.subTest(cmd=cmd): items = split.split(cmd, keep=True) self.assertEqual(''.join(items), cmd)
def _split_args(self, argstr, keep): """Split the arguments from an arg string. Args: argstr: An argument string. keep: Whether to keep special chars and whitespace Return: A list containing the splitted strings. """ if not argstr: self._args = [] elif self._cmd.maxsplit is None: self._args = split.split(argstr, keep=keep) else: # If split=False, we still want to split the flags, but not # everything after that. # We first split the arg string and check the index of the first # non-flag args, then we re-split again properly. # example: # # input: "--foo -v bar baz" # first split: ['--foo', '-v', 'bar', 'baz'] # 0 1 2 3 # second split: ['--foo', '-v', 'bar baz'] # (maxsplit=2) split_args = split.simple_split(argstr, keep=keep) flag_arg_count = 0 for i, arg in enumerate(split_args): arg = arg.strip() if arg.startswith('-'): if arg.lstrip('-') in self._cmd.flags_with_args: flag_arg_count += 1 else: self._args = [] maxsplit = i + self._cmd.maxsplit + flag_arg_count args = split.simple_split(argstr, keep=keep, maxsplit=maxsplit) for s in args: # remove quotes and replace \" by " if s == '""' or s == "''": s = '' else: s = re.sub(r"""(^|[^\\])["']""", r'\1', s) s = re.sub(r"""\\(["'])""", r'\1', s) self._args.append(s) break else: # If there are only flags, we got it right on the first try # already. self._args = split_args
def _split_args(self, argstr, keep): """Split the arguments from an arg string. Args: argstr: An argument string. keep: Whether to keep special chars and whitespace Return: A list containing the splitted strings. """ if not argstr: self._args = [] elif self._cmd.maxsplit is None: self._args = split.split(argstr, keep=keep) else: # If split=False, we still want to split the flags, but not # everything after that. # We first split the arg string and check the index of the first # non-flag args, then we re-split again properly. # example: # # input: "--foo -v bar baz" # first split: ['--foo', '-v', 'bar', 'baz'] # 0 1 2 3 # second split: ['--foo', '-v', 'bar baz'] # (maxsplit=2) split_args = split.simple_split(argstr, keep=keep) flag_arg_count = 0 for i, arg in enumerate(split_args): arg = arg.strip() if arg.startswith('-'): if arg.lstrip('-') in self._cmd.flags_with_args: flag_arg_count += 1 else: self._args = [] maxsplit = i + self._cmd.maxsplit + flag_arg_count args = split.simple_split(argstr, keep=keep, maxsplit=maxsplit) for s in args: # remove quotes and replace \" by " s = re.sub(r"""(^|[^\\])["']""", r'\1', s) s = re.sub(r"""\\(["'])""", r'\1', s) self._args.append(s) break else: # If there are only flags, we got it right on the first try # already. self._args = split_args
def _split_args(self, cmd: command.Command, argstr: str, keep: bool) -> List[str]: """Split the arguments from an arg string. Args: cmd: The command we're currently handling. argstr: An argument string. keep: Whether to keep special chars and whitespace Return: A list containing the split strings. """ if not argstr: return [] elif cmd.maxsplit is None: return split.split(argstr, keep=keep) else: # If split=False, we still want to split the flags, but not # everything after that. # We first split the arg string and check the index of the first # non-flag args, then we re-split again properly. # example: # # input: "--foo -v bar baz" # first split: ['--foo', '-v', 'bar', 'baz'] # 0 1 2 3 # second split: ['--foo', '-v', 'bar baz'] # (maxsplit=2) split_args = split.simple_split(argstr, keep=keep) flag_arg_count = 0 for i, arg in enumerate(split_args): arg = arg.strip() if arg.startswith('-'): if arg in cmd.flags_with_args: flag_arg_count += 1 else: maxsplit = i + cmd.maxsplit + flag_arg_count return split.simple_split(argstr, keep=keep, maxsplit=maxsplit) # If there are only flags, we got it right on the first try # already. return split_args
def _split_args(self, cmd, argstr, keep): """Split the arguments from an arg string. Args: cmd: The command we're currently handling. argstr: An argument string. keep: Whether to keep special chars and whitespace Return: A list containing the split strings. """ if not argstr: return [] elif cmd.maxsplit is None: return split.split(argstr, keep=keep) else: # If split=False, we still want to split the flags, but not # everything after that. # We first split the arg string and check the index of the first # non-flag args, then we re-split again properly. # example: # # input: "--foo -v bar baz" # first split: ['--foo', '-v', 'bar', 'baz'] # 0 1 2 3 # second split: ['--foo', '-v', 'bar baz'] # (maxsplit=2) split_args = split.simple_split(argstr, keep=keep) flag_arg_count = 0 for i, arg in enumerate(split_args): arg = arg.strip() if arg.startswith('-'): if arg in cmd.flags_with_args: flag_arg_count += 1 else: maxsplit = i + cmd.maxsplit + flag_arg_count return split.simple_split(argstr, keep=keep, maxsplit=maxsplit) # If there are only flags, we got it right on the first try # already. return split_args
def parse(self, text, *, fallback=False, keep=False): """Split the commandline text into command and arguments. Args: text: Text to parse. fallback: Whether to do a fallback splitting when the command was unknown. keep: Whether to keep special chars and whitespace Return: A ParseResult tuple. """ cmdstr, sep, argstr = text.partition(' ') count, cmdstr = self._parse_count(cmdstr) if not cmdstr and not fallback: raise cmdexc.NoSuchCommandError("No command given") if self._partial_match: cmdstr = self._completion_match(cmdstr) try: cmd = cmdutils.cmd_dict[cmdstr] except KeyError: if not fallback: raise cmdexc.NoSuchCommandError( '{}: no such command'.format(cmdstr)) cmdline = split.split(text, keep=keep) return ParseResult(cmd=None, args=None, cmdline=cmdline, count=count) args = self._split_args(cmd, argstr, keep) if keep and args: cmdline = [cmdstr, sep + args[0]] + args[1:] elif keep: cmdline = [cmdstr, sep] else: cmdline = [cmdstr] + args[:] return ParseResult(cmd=cmd, args=args, cmdline=cmdline, count=count)
def _partition(self): """Divide the commandline text into chunks around the cursor position. Return: ([parts_before_cursor], 'part_under_cursor', [parts_after_cursor]) """ text = self._cmd.text()[len(self._cmd.prefix()):] if not text or not text.strip(): # Only ":", empty part under the cursor with nothing before/after return [], '', [] try: parse_result = parser.CommandParser().parse(text, keep=True) except cmdexc.NoSuchCommandError: cmdline = split.split(text, keep=True) else: cmdline = parse_result.cmdline parts = [x for x in cmdline if x] pos = self._cmd.cursorPosition() - len(self._cmd.prefix()) pos = min(pos, len(text)) # Qt treats 2-byte UTF-16 chars as 2 chars log.completion.debug(f'partitioning {parts} around position {pos}') for i, part in enumerate(parts): pos -= len(part) if pos <= 0: if part[pos - 1:pos + 1].isspace(): # cursor is in a space between two existing words parts.insert(i, '') prefix = [x.strip() for x in parts[:i]] # pylint: disable-next=unnecessary-list-index-lookup center = parts[i].strip() # strip trailing whitespace included as a separate token postfix = [x.strip() for x in parts[i + 1:] if not x.isspace()] log.completion.debug( f"partitioned: {prefix} '{center}' {postfix}") return prefix, center, postfix raise utils.Unreachable(f"Not all parts consumed: {parts}")
def test_split(self, split_test_case): """Test splitting.""" items = split.split(split_test_case.input) assert items == split_test_case.keep
def test_split(keep, s): split.split(s, keep=keep)
def test_split_keep(self, split_test_case): """Test splitting with keep=True.""" items = split.split(split_test_case.inp, keep=True) assert items == split_test_case.no_keep
def test_split_keep_original(self, split_test_case): """Test if splitting with keep=True yields the original string.""" items = split.split(split_test_case.inp, keep=True) assert ''.join(items) == split_test_case.inp
def test_split_keep_original(self, split_test_case): """Test if splitting with keep=True yields the original string.""" items = split.split(split_test_case.input, keep=True) assert ''.join(items) == split_test_case.input
def test_split_keep(self, split_test_case): """Test splitting with keep=True.""" items = split.split(split_test_case.input, keep=True) assert items == split_test_case.no_keep
def test_split(self, split_test_case): """Test splitting.""" items = split.split(split_test_case.inp) assert items == split_test_case.keep