Example #1
0
def test_partial_string(leaders, prefix, quote):
    (l, l_len), (f, f_len) = leaders
    s = prefix + quote
    t = s + "test string" + quote
    t_len = len(t)
    # single string
    test_string = l + t + f
    obs = check_for_partial_string(test_string)
    exp = l_len, l_len + t_len, s
    assert obs == exp
    # single partial
    test_string = l + f + s + "test string"
    obs = check_for_partial_string(test_string)
    exp = l_len + f_len, None, s
    assert obs == exp
    # two strings
    test_string = l + t + f + l + t + f
    obs = check_for_partial_string(test_string)
    exp = (l_len + t_len + f_len + l_len), (l_len + t_len + f_len + l_len + t_len), s
    assert obs == exp
    # one string, one partial
    test_string = l + t + f + l + s + "test string"
    obs = check_for_partial_string(test_string)
    exp = l_len + t_len + f_len + l_len, None, s
    assert obs == exp
Example #2
0
def test_partial_string(leaders, prefix, quote):
    (l, l_len), (f, f_len) = leaders
    s = prefix + quote
    t = s + "test string" + quote
    t_len = len(t)
    # single string
    test_string = l + t + f
    obs = check_for_partial_string(test_string)
    exp = l_len, l_len + t_len, s
    assert obs == exp
    # single partial
    test_string = l + f + s + "test string"
    obs = check_for_partial_string(test_string)
    exp = l_len + f_len, None, s
    assert obs == exp
    # two strings
    test_string = l + t + f + l + t + f
    obs = check_for_partial_string(test_string)
    exp = (l_len + t_len + f_len + l_len), (l_len + t_len + f_len + l_len +
                                            t_len), s
    assert obs == exp
    # one string, one partial
    test_string = l + t + f + l + s + "test string"
    obs = check_for_partial_string(test_string)
    exp = l_len + t_len + f_len + l_len, None, s
    assert obs == exp
Example #3
0
 def try_parse_string_literal(raw_arg: str) -> Optional[CommandArg]:
     """Try to parse this as a single string literal. can be partial
     For example:
         "wow"
         "a b
         '''a b 'c' "d"
     """
     startix, endix, quote = check_for_partial_string(raw_arg)
     if startix != 0 or endix not in (
         None,  # the arg doesn't start with a string literal
         len(raw_arg),  # the string literal ends in the middle of the arg
     ):
         # xonsh won't treat it as a string literal
         return None
     else:
         if endix is None:
             # no closing quote
             return CommandArg(raw_arg[len(quote) : endix], opening_quote=quote)
         else:
             closing_quote_len = quote.count('"') + quote.count("'")
             return CommandArg(
                 value=raw_arg[len(quote) : -closing_quote_len],
                 closing_quote=raw_arg[-closing_quote_len:],
                 opening_quote=quote,
             )
Example #4
0
 def compile(self, src):
     """Compiles source code and returns the (possibly modified) source and
     a valid code object.
     """
     _cache = should_use_cache(self.execer, 'single')
     if _cache:
         codefname = code_cache_name(src)
         cachefname = get_cache_filename(codefname, code=True)
         usecache, code = code_cache_check(cachefname)
         if usecache:
             self.reset_buffer()
             return src, code
     try:
         code = self.execer.compile(src,
                                    mode='single',
                                    glbs=self.ctx,
                                    locs=None)
         if _cache:
             update_cache(code, cachefname)
         self.reset_buffer()
     except SyntaxError:
         partial_string_info = check_for_partial_string(src)
         in_partial_string = (partial_string_info[0] is not None
                              and partial_string_info[1] is None)
         if (src == '\n' or src.endswith('\n\n')) and not in_partial_string:
             self.reset_buffer()
             print_exception()
             return src, None
         self.need_more_lines = True
     except Exception:  # pylint: disable=broad-except
         self.reset_buffer()
         print_exception()
         return src, None
     return src, code
Example #5
0
def _path_from_partial_string(inp, pos=None):
    if pos is None:
        pos = len(inp)
    partial = inp[:pos]
    startix, endix, quote = check_for_partial_string(partial)
    _post = ""
    if startix is None:
        return None
    elif endix is None:
        string = partial[startix:]
    else:
        if endix != pos:
            _test = partial[endix:pos]
            if not any(i == ' ' for i in _test):
                _post = _test
            else:
                return None
        string = partial[startix:endix]
    end = re.sub(RE_STRING_START, '', quote)
    _string = string
    if not _string.endswith(end):
        _string = _string + end
    try:
        val = ast.literal_eval(_string)
    except SyntaxError:
        return None
    if isinstance(val, bytes):
        env = builtins.__xonsh_env__
        val = val.decode(encoding=env.get('XONSH_ENCODING'),
                         errors=env.get('XONSH_ENCODING_ERRORS'))
    return string + _post, val + _post, quote, end
Example #6
0
 def compile(self, src):
     """Compiles source code and returns the (possibly modified) source and
     a valid code object.
     """
     _cache = should_use_cache(self.execer, 'single')
     if _cache:
         codefname = code_cache_name(src)
         cachefname = get_cache_filename(codefname, code=True)
         usecache, code = code_cache_check(cachefname)
         if usecache:
             self.reset_buffer()
             return src, code
     try:
         code = self.execer.compile(src,
                                    mode='single',
                                    glbs=self.ctx,
                                    locs=None)
         if _cache:
             update_cache(code, cachefname)
         self.reset_buffer()
     except SyntaxError:
         partial_string_info = check_for_partial_string(src)
         in_partial_string = (partial_string_info[0] is not None and
                              partial_string_info[1] is None)
         if (src == '\n' or src.endswith('\n\n')) and not in_partial_string:
             self.reset_buffer()
             print_exception()
             return src, None
         self.need_more_lines = True
         code = None
     except Exception:  # pylint: disable=broad-except
         self.reset_buffer()
         print_exception()
         code = None
     return src, code
Example #7
0
def carriage_return(b, cli, *, autoindent=True):
    """
    Preliminary parser to determine if 'Enter' key should send command to
    the xonsh parser for execution or should insert a newline for continued
    input.

    Current 'triggers' for inserting a newline are:
    - Not on first line of buffer and line is non-empty
    - Previous character is a colon (covers if, for, etc...)
    - User is in an open paren-block
    - Line ends with backslash
    - Any text exists below cursor position (relevant when editing previous
    multiline blocks)
    """
    doc = b.document
    at_end_of_line = _is_blank(doc.current_line_after_cursor)
    current_line_blank = _is_blank(doc.current_line)

    indent = env.get('INDENT') if autoindent else ''

    partial_string_info = check_for_partial_string(doc.text)
    in_partial_string = (partial_string_info[0] is not None and
                         partial_string_info[1] is None)

    # indent after a colon
    if (doc.current_line_before_cursor.strip().endswith(':') and
            at_end_of_line):
        b.newline(copy_margin=autoindent)
        b.insert_text(indent, fire_event=False)
    # if current line isn't blank, check dedent tokens
    elif (not current_line_blank and
            doc.current_line.split(maxsplit=1)[0] in DEDENT_TOKENS and
            doc.line_count > 1):
        b.newline(copy_margin=autoindent)
        b.delete_before_cursor(count=len(indent))
    elif (not doc.on_first_line and
            not current_line_blank):
        b.newline(copy_margin=autoindent)
    elif (doc.char_before_cursor == '\\' and
            not (not builtins.__xonsh_env__.get('FORCE_POSIX_PATHS')
                 and ON_WINDOWS)):
        b.newline(copy_margin=autoindent)
    elif (doc.find_next_word_beginning() is not None and
            (any(not _is_blank(i)
                 for i
                 in doc.lines_from_current[1:]))):
        b.newline(copy_margin=autoindent)
    elif not current_line_blank and not can_compile(doc.text):
        b.newline(copy_margin=autoindent)
    elif current_line_blank and in_partial_string:
        b.newline(copy_margin=autoindent)
    else:
        b.accept_action.validate_and_handle(cli, b)
Example #8
0
def test_partial_string():
    # single string at start
    yield assert_equal, check_for_partial_string('no strings here'), (None,
                                                                      None,
                                                                      None)
    yield assert_equal, check_for_partial_string(''), (None, None, None)
    for s, e in _startend.items():
        _test = s + inners + e
        for l in _leaders:
            for f in _leaders:
                # single string
                _res = check_for_partial_string(l + _test + f)
                yield assert_equal, _res, (len(l), len(l) + len(_test), s)
                # single partial
                _res = check_for_partial_string(l + f + s + inners)
                yield assert_equal, _res, (len(l + f), None, s)
                for s2, e2 in _startend.items():
                    _test2 = s2 + inners + e2
                    for l2 in _leaders:
                        for f2 in _leaders:
                            # two strings
                            _res = check_for_partial_string(l + _test + f +
                                                            l2 + _test2 + f2)
                            yield assert_equal, _res, (len(l + _test + f + l2),
                                                       len(l + _test + f + l2 +
                                                           _test2), s2)
                            # one string, one partial
                            _res = check_for_partial_string(l + _test + f +
                                                            l2 + s2 + inners)
                            yield assert_equal, _res, (len(l + _test + f + l2),
                                                       None, s2)
Example #9
0
def expand_abbrev(buffer):
    abbrevs = getattr(builtins, "abbrevs", None)
    if abbrevs is None:
        return
    document = buffer.document
    word = document.get_word_before_cursor(WORD=True)
    if word in abbrevs.keys():
        partial = document.text[: document.cursor_position]
        startix, endix, quote = check_for_partial_string(partial)
        if startix is not None and endix is None:
            return
        buffer.delete_before_cursor(count=len(word))
        buffer.insert_text(abbrevs[word])
Example #10
0
def carriage_return(b, cli, *, autoindent=True):
    """
    Preliminary parser to determine if 'Enter' key should send command to
    the xonsh parser for execution or should insert a newline for continued
    input.

    Current 'triggers' for inserting a newline are:
    - Not on first line of buffer and line is non-empty
    - Previous character is a colon (covers if, for, etc...)
    - User is in an open paren-block
    - Line ends with backslash
    - Any text exists below cursor position (relevant when editing previous
    multiline blocks)
    """
    doc = b.document
    at_end_of_line = _is_blank(doc.current_line_after_cursor)
    current_line_blank = _is_blank(doc.current_line)

    indent = env.get('INDENT') if autoindent else ''

    partial_string_info = check_for_partial_string(doc.text)
    in_partial_string = (partial_string_info[0] is not None
                         and partial_string_info[1] is None)

    # indent after a colon
    if (doc.current_line_before_cursor.strip().endswith(':')
            and at_end_of_line):
        b.newline(copy_margin=autoindent)
        b.insert_text(indent, fire_event=False)
    # if current line isn't blank, check dedent tokens
    elif (not current_line_blank
          and doc.current_line.split(maxsplit=1)[0] in DEDENT_TOKENS
          and doc.line_count > 1):
        b.newline(copy_margin=autoindent)
        b.delete_before_cursor(count=len(indent))
    elif (not doc.on_first_line and not current_line_blank):
        b.newline(copy_margin=autoindent)
    elif (doc.char_before_cursor == '\\'
          and not (not builtins.__xonsh_env__.get('FORCE_POSIX_PATHS')
                   and ON_WINDOWS)):
        b.newline(copy_margin=autoindent)
    elif (doc.find_next_word_beginning() is not None
          and (any(not _is_blank(i) for i in doc.lines_from_current[1:]))):
        b.newline(copy_margin=autoindent)
    elif not current_line_blank and not can_compile(doc.text):
        b.newline(copy_margin=autoindent)
    elif current_line_blank and in_partial_string:
        b.newline(copy_margin=autoindent)
    else:
        b.accept_action.validate_and_handle(cli, b)
Example #11
0
 def completedefault(self, prefix, line, begidx, endidx):
     """Implements tab-completion for text."""
     if self.completer is None:
         return []
     rl_completion_suppress_append()  # this needs to be called each time
     _rebind_case_sensitive_completions()
     _s, _e, _q = check_for_partial_string(line)
     if _s is not None:
         if _e is not None and ' ' in line[_e:]:
             mline = line.rpartition(' ')[2]
         else:
             mline = line[_s:]
     else:
         mline = line.rpartition(' ')[2]
     offs = len(mline) - len(prefix)
     return [i[offs:] for i in self.completer.complete(prefix, line,
                                                       begidx, endidx,
                                                       ctx=self.ctx)[0]]
Example #12
0
 def compile(self, src):
     """Compiles source code and returns the (possibly modified) source and
     a valid code object.
     """
     _cache = should_use_cache(self.execer, "single")
     if _cache:
         codefname = code_cache_name(src)
         cachefname = get_cache_filename(codefname, code=True)
         usecache, code = code_cache_check(cachefname)
         if usecache:
             self.reset_buffer()
             return src, code
     lincont = get_line_continuation()
     if src.endswith(lincont + "\n"):
         self.need_more_lines = True
         return src, None
     try:
         code = self.execer.compile(
             src,
             mode="single",
             glbs=self.ctx,
             locs=None,
             filename="<stdin>",
             compile_empty_tree=False,
         )
         if _cache:
             update_cache(code, cachefname)
         self.reset_buffer()
     except SyntaxError:
         partial_string_info = check_for_partial_string(src)
         in_partial_string = (partial_string_info[0] is not None
                              and partial_string_info[1] is None)
         if (src == "\n" or src.endswith("\n\n")) and not in_partial_string:
             self.reset_buffer()
             print_exception()
             return src, None
         self.need_more_lines = True
         code = None
     except Exception:  # pylint: disable=broad-except
         self.reset_buffer()
         print_exception()
         code = None
     return src, code
Example #13
0
    def expand(self, buffer: Buffer) -> bool:
        """expand the given abbr text. Return true if cursor position changed."""
        if not abbrevs:
            return False
        document = buffer.document
        word = document.get_word_before_cursor(WORD=True)
        if word in abbrevs.keys():
            partial = document.text[:document.cursor_position]
            startix, endix, quote = check_for_partial_string(partial)
            if startix is not None and endix is None:
                return False
            text = get_abbreviated(word, buffer)

            buffer.delete_before_cursor(count=len(word))
            buffer.insert_text(text)

            self.last_expanded = _LastExpanded(word, text)
            if EDIT_SYMBOL in text:
                set_cursor_position(buffer, text)
                return True
        return False
Example #14
0
def _path_from_partial_string(inp, pos=None):
    if pos is None:
        pos = len(inp)
    partial = inp[:pos]
    startix, endix, quote = xt.check_for_partial_string(partial)
    _post = ""
    if startix is None:
        return None
    elif endix is None:
        string = partial[startix:]
    else:
        if endix != pos:
            _test = partial[endix:pos]
            if not any(i == " " for i in _test):
                _post = _test
            else:
                return None
        string = partial[startix:endix]

    # If 'pr'/'rp', treat as raw string, otherwise strip leading 'p'
    pstring_pre = _get_normalized_pstring_quote(quote)[0]
    if pstring_pre == "pr":
        string = f"r{string[2:]}"
    elif pstring_pre == "p":
        string = string[1:]

    end = xt.RE_STRING_START.sub("", quote)
    _string = string
    if not _string.endswith(end):
        _string = _string + end
    try:
        val = ast.literal_eval(_string)
    except (SyntaxError, ValueError):
        return None
    if isinstance(val, bytes):
        env = builtins.__xonsh__.env
        val = val.decode(
            encoding=env.get("XONSH_ENCODING"), errors=env.get("XONSH_ENCODING_ERRORS")
        )
    return string + _post, val + _post, quote, end
Example #15
0
 def push(self, line):
     """Pushes a line onto the buffer and compiles the code in a way that
     enables multiline input.
     """
     code = None
     self.buffer.append(line)
     if self.need_more_lines:
         return None, code
     src = ''.join(self.buffer)
     _cache = should_use_cache(self.execer, 'single')
     if _cache:
         codefname = code_cache_name(src)
         cachefname = get_cache_filename(codefname, code=True)
         usecache, code = code_cache_check(cachefname)
         if usecache:
             self.reset_buffer()
             return src, code
     try:
         code = self.execer.compile(src,
                                    mode='single',
                                    glbs=self.ctx,
                                    locs=None)
         if _cache:
             update_cache(code, cachefname)
         self.reset_buffer()
     except SyntaxError:
         partial_string_info = check_for_partial_string(src)
         in_partial_string = (partial_string_info[0] is not None and
                              partial_string_info[1] is None)
         if ((line == '\n' and not in_partial_string)):
             self.reset_buffer()
             print_exception()
             return src, None
         self.need_more_lines = True
     except Exception:  # pylint: disable=broad-except
         self.reset_buffer()
         print_exception()
         return src, None
     return src, code
Example #16
0
 def push(self, line):
     """Pushes a line onto the buffer and compiles the code in a way that
     enables multiline input.
     """
     code = None
     self.buffer.append(line)
     if self.need_more_lines:
         return None, code
     src = ''.join(self.buffer)
     _cache = should_use_cache(self.execer, 'single')
     if _cache:
         codefname = code_cache_name(src)
         cachefname = get_cache_filename(codefname, code=True)
         usecache, code = code_cache_check(cachefname)
         if usecache:
             self.reset_buffer()
             return src, code
     try:
         code = self.execer.compile(src,
                                    mode='single',
                                    glbs=self.ctx,
                                    locs=None)
         if _cache:
             update_cache(code, cachefname)
         self.reset_buffer()
     except SyntaxError:
         partial_string_info = check_for_partial_string(src)
         in_partial_string = (partial_string_info[0] is not None
                              and partial_string_info[1] is None)
         if ((line == '\n' and not in_partial_string)):
             self.reset_buffer()
             print_exception()
             return src, None
         self.need_more_lines = True
     except Exception:  # pylint: disable=broad-except
         self.reset_buffer()
         print_exception()
         return src, None
     return src, code
Example #17
0
def test_partial_string():
    # single string at start
    yield assert_equal, check_for_partial_string('no strings here'), (None, None, None)
    yield assert_equal, check_for_partial_string(''), (None, None, None)
    for s,e in _startend.items():
        _test = s + inners + e
        for l in _leaders:
            for f in _leaders:
                # single string
                _res = check_for_partial_string(l + _test + f)
                yield assert_equal, _res, (len(l), len(l) + len(_test), s)
                # single partial
                _res = check_for_partial_string(l + f + s + inners)
                yield assert_equal, _res, (len(l+f), None, s)
                for s2, e2 in _startend.items():
                    _test2 = s2 + inners + e2
                    for l2 in _leaders:
                        for f2 in _leaders:
                            # two strings
                            _res = check_for_partial_string(l + _test + f + l2 + _test2 + f2)
                            yield assert_equal, _res, (len(l+_test+f+l2), len(l+_test+f+l2+_test2), s2)
                            # one string, one partial
                            _res = check_for_partial_string(l + _test + f + l2 + s2 + inners)
                            yield assert_equal, _res, (len(l+_test+f+l2), None, s2)
Example #18
0
def test_partial_string_none(inp):
    assert check_for_partial_string(inp) == (None, None, None)
Example #19
0
def test_partial_string_none(inp):
    assert check_for_partial_string(inp) == (None, None, None)