Example #1
0
def TildeDetectAssign(w):
    # type: (compound_word) -> None
    """MUTATES its argument."""
    parts = w.parts
    n = len(parts)

    parts.append(None)  # sentinel
    do_expand = True
    for i in xrange(n):
        cur = parts[i]

        # Replace with tilde sub
        if do_expand and LiteralId(cur) == Id.Lit_TildeLike:
            next_part = parts[i + 1]
            if next_part:
                is_tilde = (LiteralId(next_part) == Id.Lit_Colon or
                            (LiteralId(next_part) == Id.Lit_Chars
                             and cast(Token, next_part).val.startswith('/')))
            else:
                is_tilde = True  # you can expand :~

            if is_tilde:
                parts[i] = word_part.TildeSub(cast(Token, cur))

        # For next iteration
        do_expand = LiteralId(cur) == Id.Lit_Colon

    parts.pop()  # remove sentinel
Example #2
0
File: word_.py Project: o11c/oil
def TildeDetect(UP_w):
    # type: (word_t) -> Optional[compound_word]
    """Detect tilde expansion in a word.

  It might begin with  Literal that needs to be turned into a TildeSub.
  (It depends on whether the second token begins with slash).

  If so, it return a new word.  Otherwise return None.

  NOTE:
  - The regex for Lit_TildeLike could be expanded.  Right now it's
    conservative, like Lit_Chars without the /.
  - It's possible to write this in a mutating style, since only the first token
    is changed.  But note that we CANNOT know this during lexing.
  """
    # NOTE: BracedTree, Empty, etc. can't be tilde expanded
    if UP_w.tag_() != word_e.Compound:
        return None

    w = cast(compound_word, UP_w)
    assert w.parts, w

    UP_part0 = w.parts[0]
    if _LiteralId(UP_part0) != Id.Lit_TildeLike:
        return None
    tok0 = cast(Token, UP_part0)

    if len(w.parts) == 1:  # can't be zero
        tilde_part = word_part.TildeSub(tok0)
        return compound_word([tilde_part])

    UP_part1 = w.parts[1]
    # NOTE: We could inspect the raw tokens.
    if _LiteralId(UP_part1) == Id.Lit_Chars:
        tok = cast(Token, UP_part1)
        if tok.val.startswith('/'):
            tilde_part_ = word_part.TildeSub(tok0)  # type: word_part_t

            parts = [tilde_part_]
            parts.extend(w.parts[1:])
            return compound_word(parts)

    # It could be something like '~foo:bar', which doesn't have a slash.
    return None
Example #3
0
def TildeDetect(w):
    # type: (word_t) -> Optional[word_t]
    """Detect tilde expansion in a word.

  It might begin with  Literal that needs to be turned into a TildeSub.
  (It depends on whether the second token begins with slash).

  If so, it return a new word.  Otherwise return None.

  NOTE:
  - The regex for Lit_TildeLike could be expanded.  Right now it's
    conservative, like Lit_Chars without the /.
  - It's possible to write this in a mutating style, since only the first token
    is changed.  But note that we CANNOT know this during lexing.
  """
    # NOTE: BracedTree, Empty, etc. can't be tilde expanded
    if not isinstance(w, word__Compound):
        return None

    assert w.parts, w

    part0 = w.parts[0]
    if _LiteralId(part0) != Id.Lit_TildeLike:
        return None
    assert isinstance(part0, word_part__Literal)  # for MyPy

    if len(w.parts) == 1:  # can't be zero
        tilde_part = word_part.TildeSub(part0.token)
        return word.Compound([tilde_part])

    part1 = w.parts[1]
    # NOTE: We could inspect the raw tokens.
    if _LiteralId(part1) == Id.Lit_Chars:
        assert isinstance(part1, word_part__Literal)  # for MyPy
        if part1.token.val.startswith('/'):
            tilde_part_ = word_part.TildeSub(part0.token)  # type: word_part_t
            return word.Compound([tilde_part_] + w.parts[1:])

    # It could be something like '~foo:bar', which doesn't have a slash.
    return None
Example #4
0
def TildeDetect(UP_w):
    # type: (word_t) -> Optional[compound_word]
    """Detect tilde expansion in a word.

  It might begin with  Literal that needs to be turned into a TildeSub.
  (It depends on whether the second token begins with slash).

  If so, it return a new word.  Otherwise return None.

  NOTE:
  - The regex for Lit_TildeLike could be expanded.  Right now it's
    conservative, like Lit_Chars without the /.
  - It's possible to write this in a mutating style, since only the first token
    is changed.  But note that we CANNOT know this during lexing.
  """
    # NOTE: BracedTree, Empty, etc. can't be tilde expanded
    if UP_w.tag_() != word_e.Compound:
        return None

    w = cast(compound_word, UP_w)
    if len(w.parts) == 0:  # ${a-} has no parts
        return None

    part0 = w.parts[0]
    if LiteralId(part0) != Id.Lit_TildeLike:
        return None

    tok0 = cast(Token, part0)
    new_parts = [word_part.TildeSub(tok0)]  # type: List[word_part_t]

    if len(w.parts) == 1:  # can't be zero
        return compound_word(new_parts)

    part1 = w.parts[1]
    id_ = LiteralId(part1)

    # Lit_Slash is for ${x-~/foo}
    if id_ == Id.Lit_Slash:  # we handled ${x//~/} delimiter earlier,
        new_parts.extend(w.parts[1:])
        return compound_word(new_parts)

    # Lit_Chars is for ~/foo,
    if id_ == Id.Lit_Chars and cast(Token, part1).val.startswith('/'):
        new_parts.extend(w.parts[1:])
        return compound_word(new_parts)

    # It could be something like '~foo:bar', which doesn't have a slash.
    return None