MCPcopy Index your code
hub / github.com/codeaashu/claude-code / tryParseRedirect

Function tryParseRedirect

src/utils/bash/bashParser.ts:1623–1859  ·  view source on GitHub ↗

* Parse a redirect operator + destination(s). * @param greedy When true, file_redirect consumes repeat1($._literal) per * grammar's prec.left — `cmd >f a b c` attaches `a b c` to the redirect. * When false (preRedirect context), takes only 1 destination because * command's dynamic preceden

(P: ParseState, greedy = false)

Source from the content-addressed store, hash-verified

1621 * command's dynamic precedence beats redirected_statement's prec(-1).
1622 */
1623function tryParseRedirect(P: ParseState, greedy = false): TsNode | null {
1624 const save = saveLex(P.L)
1625 skipBlanks(P.L)
1626 // File descriptor prefix?
1627 let fd: TsNode | null = null
1628 if (isDigit(peek(P.L))) {
1629 const startB = P.L.b
1630 let j = P.L.i
1631 while (j < P.L.len && isDigit(P.L.src[j]!)) j++
1632 const after = j < P.L.len ? P.L.src[j]! : ''
1633 if (after === '>' || after === '<') {
1634 while (P.L.i < j) advance(P.L)
1635 fd = mk(P, 'file_descriptor', startB, P.L.b, [])
1636 }
1637 }
1638 const t = nextToken(P.L, 'arg')
1639 if (t.type !== 'OP') {
1640 restoreLex(P.L, save)
1641 return null
1642 }
1643 const v = t.value
1644 if (v === '<<<') {
1645 const op = leaf(P, '<<<', t)
1646 skipBlanks(P.L)
1647 const target = parseWord(P, 'arg')
1648 const end = target ? target.endIndex : op.endIndex
1649 const kids = target ? [op, target] : [op]
1650 return mk(
1651 P,
1652 'herestring_redirect',
1653 fd ? fd.startIndex : op.startIndex,
1654 end,
1655 fd ? [fd, ...kids] : kids,
1656 )
1657 }
1658 if (v === '<<' || v === '<<-') {
1659 const op = leaf(P, v, t)
1660 // Heredoc start — delimiter word (may be quoted)
1661 skipBlanks(P.L)
1662 const dStart = P.L.b
1663 let quoted = false
1664 let delim = ''
1665 const dc = peek(P.L)
1666 if (dc === "'" || dc === '"') {
1667 quoted = true
1668 advance(P.L)
1669 while (P.L.i < P.L.len && peek(P.L) !== dc) {
1670 delim += peek(P.L)
1671 advance(P.L)
1672 }
1673 if (P.L.i < P.L.len) advance(P.L)
1674 } else if (dc === '\\') {
1675 // Backslash-escaped delimiter: \X — exactly one escaped char, body is
1676 // quoted (literal). Covers <<\EOF <<\' <<\\ etc.
1677 quoted = true
1678 advance(P.L)
1679 if (P.L.i < P.L.len && peek(P.L) !== '\n') {
1680 delim += peek(P.L)

Callers 2

parseSimpleCommandFunction · 0.85
maybeRedirectFunction · 0.85

Calls 15

saveLexFunction · 0.85
skipBlanksFunction · 0.85
isDigitFunction · 0.85
advanceFunction · 0.85
mkFunction · 0.85
nextTokenFunction · 0.85
restoreLexFunction · 0.85
leafFunction · 0.85
parseWordFunction · 0.85
isIdentCharFunction · 0.85
isHeredocDelimCharFunction · 0.85
isRedirectLiteralStartFunction · 0.85

Tested by

no test coverage detected