[ Web Proxy ]
URL:
Viewing: https://raw.githubusercontent.com/studiovc/bpython/master/bpython/line.py [Back]  [Original]

"""Extracting and changing portions of the current line

All functions take cursor offset from the beginning of the line and the line of
Python code, and return None, or a tuple of the start index, end index, and the
word."""

from itertools import chain
from collections import namedtuple

from .lazyre import LazyReCompile

LinePart = namedtuple("LinePart", ["start", "stop", "word"])

current_word_re = LazyReCompile(r"(?= cursor_offset:
            return LinePart(m.start(1), m.end(1), m.group(1))
    return None


current_string_re = LazyReCompile(
    '''(?P(?:""")|"|(?:''\')|')(?:((?P.+?)(?P=open))|'''
    """(?P.+))"""
)


def current_string(cursor_offset, line):
    """If inside a string of nonzero length, return the string (excluding
    quotes)

    Weaker than bpython.Repl's current_string, because that checks that a
    string is a string based on previous lines in the buffer."""
    for m in current_string_re.finditer(line):
        i = 3 if m.group(3) else 4
        if m.start(i) = cursor_offset:
            return LinePart(m.start(i), m.end(i), m.group(i))
    return None


current_object_re = LazyReCompile(r"([\w_][\w0-9_]*)[.]")


def current_object(cursor_offset, line):
    """If in attribute completion, the object on which attribute should be
    looked up."""
    match = current_word(cursor_offset, line)
    if match is None:
        return None
    start, end, word = match
    matches = current_object_re.finditer(word)
    s = ""
    for m in matches:
        if m.end(1) + start < cursor_offset:
            if s:
                s += "."
            s += m.group(1)
    if not s:
        return None
    return LinePart(start, start + len(s), s)


current_object_attribute_re = LazyReCompile(r"([\w_][\w0-9_]*)[.]?")


def current_object_attribute(cursor_offset, line):
    """If in attribute completion, the attribute being completed"""
    # TODO replace with more general current_expression_attribute
    match = current_word(cursor_offset, line)
    if match is None:
        return None
    start, end, word = match
    matches = current_object_attribute_re.finditer(word)
    next(matches)
    for m in matches:
        if (
            m.start(1) + start = cursor_offset
        ):
            return LinePart(m.start(1) + start, m.end(1) + start, m.group(1))
    return None


current_from_import_from_re = LazyReCompile(
    r"from ([\w0-9_.]*)(?:\s+import\s+([\w0-9_]+[,]?\s*)+)*"
)


def current_from_import_from(cursor_offset, line):
    """If in from import completion, the word after from

    returns None if cursor not in or just after one of the two interesting
    parts of an import: from (module) import (name1, name2)
    """
    # TODO allow for as's
    tokens = line.split()
    if not ("from" in tokens or "import" in tokens):
        return None
    matches = current_from_import_from_re.finditer(line)
    for m in matches:
        if (m.start(1) < cursor_offset and m.end(1) >= cursor_offset) or (
            m.start(2) < cursor_offset and m.end(2) >= cursor_offset
        ):
            return LinePart(m.start(1), m.end(1), m.group(1))
    return None


current_from_import_import_re_1 = LazyReCompile(r"from\s([\w0-9_.]*)\s+import")
current_from_import_import_re_2 = LazyReCompile(r"([\w0-9_]+)")
current_from_import_import_re_3 = LazyReCompile(r"[,][ ]([\w0-9_]*)")


def current_from_import_import(cursor_offset, line):
    """If in from import completion, the word after import being completed

    returns None if cursor not in or just after one of these words
    """
    baseline = current_from_import_import_re_1.search(line)
    if baseline is None:
        return None
    match1 = current_from_import_import_re_2.search(line[baseline.end() :])
    if match1 is None:
        return None
    matches = current_from_import_import_re_3.finditer(line[baseline.end() :])
    for m in chain((match1,), matches):
        start = baseline.end() + m.start(1)
        end = baseline.end() + m.end(1)
        if start < cursor_offset and end >= cursor_offset:
            return LinePart(start, end, m.group(1))
    return None


current_import_re_1 = LazyReCompile(r"import")
current_import_re_2 = LazyReCompile(r"([\w0-9_.]+)")
current_import_re_3 = LazyReCompile(r"[,][ ]([\w0-9_.]*)")


def current_import(cursor_offset, line):
    # TODO allow for multiple as's
    baseline = current_import_re_1.search(line)
    if baseline is None:
        return None
    match1 = current_import_re_2.search(line[baseline.end() :])
    if match1 is None:
        return None
    matches = current_import_re_3.finditer(line[baseline.end() :])
    for m in chain((match1,), matches):
        start = baseline.end() + m.start(1)
        end = baseline.end() + m.end(1)
        if start < cursor_offset and end >= cursor_offset:
            return LinePart(start, end, m.group(1))


current_method_definition_name_re = LazyReCompile(r"def\s+([a-zA-Z_][\w]*)")


def current_method_definition_name(cursor_offset, line):
    """The name of a method being defined"""
    matches = current_method_definition_name_re.finditer(line)
    for m in matches:
        if m.start(1) = cursor_offset:
            return LinePart(m.start(1), m.end(1), m.group(1))
    return None


current_single_word_re = LazyReCompile(r"(?

Web Proxy Viewer  |  New URL  |  Original Page