Skip to content

Commit

Permalink
fix(packages/core): pipeStages splits command with >> incorrectly
Browse files Browse the repository at this point in the history
part of #7413
  • Loading branch information
starpit committed Jul 6, 2021
1 parent 3ca96bb commit 76f2f4c
Show file tree
Hide file tree
Showing 3 changed files with 20 additions and 12 deletions.
7 changes: 6 additions & 1 deletion packages/core/src/models/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,12 @@ export interface CommandLine<Options = ParsedOptions> {
/**
* pipeline stages, e.g. if command='a b --foo|c', the pipeStages=[['a','b, '--foo'],'c']
*/
pipeStages: { prefix?: string; stages: string[][]; redirect?: string }
pipeStages: {
prefix?: string
stages: string[][]
redirect?: string
redirector?: '>' | '>>' | '2>&1' | '>&' | '>>&'
}

/**
* the dash options parsed out in a way that pays attention to n-ary
Expand Down
19 changes: 11 additions & 8 deletions packages/core/src/repl/pipe-stages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,25 +25,28 @@ import { CommandLine } from '../models/command'
*
*/
export function splitIntoPipeStages(command: string): CommandLine['pipeStages'] {
// This covers the standard bash convention of using -- to split the
// command line into a "prefix" part and a "rest" part.
const dashDashPattern = /--\s/
const redirectPattern = /([^"'\\])>/

// This covers > and >>, but excludes '>' and ">" and \>.
// WARNING: this regexp uses negaive lookbehind. Firefox only got
// support for this in Firefox version 78 (released July 30 2020).
const redirectPattern = /\d?(?<!["'\\])((>>?)&?\d?)/

const dashDashMatch = command.match(dashDashPattern)
const pipeStartIdx = dashDashMatch ? dashDashMatch.index + '--'.length : undefined
const prefix = !dashDashMatch ? '' : command.slice(0, dashDashMatch.index).trim()

const redirectMatch = command.match(redirectPattern)
const pipeEndIdx = redirectMatch ? redirectMatch.index : undefined
const redirect = !redirectMatch
? ''
: command
.slice(pipeEndIdx)
.replace(/^\s*>/, '')
.trim()
const redirect = !redirectMatch ? '' : command.slice(redirectMatch.index + redirectMatch[0].length).trim()

const redirector = !redirectMatch ? undefined : (redirectMatch[0] as CommandLine['pipeStages']['redirector'])

const stages = split(command, false, undefined, '|', pipeStartIdx, pipeEndIdx).map(_ =>
split(_, false).map(_ => _.replace(/\\\s/g, ''))
)

return { prefix, stages, redirect }
return { prefix, stages, redirect, redirector }
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
import React from 'react'
import { Arguments } from '@kui-shell/core'

type Props = Pick<Arguments['pipeStages'], 'prefix' | 'stages' | 'redirect'> & Pick<Arguments, 'REPL'>
type Props = Pick<Arguments['pipeStages'], 'prefix' | 'stages' | 'redirect' | 'redirector'> & Pick<Arguments, 'REPL'>

export default class FancyPipeline extends React.PureComponent<Props> {
private linebreak() {
Expand All @@ -33,7 +33,7 @@ export default class FancyPipeline extends React.PureComponent<Props> {
* e.g. somePrefix -- foo | bar > baz
*/
public render() {
const { prefix, stages, redirect, REPL } = this.props
const { prefix, stages, redirect, redirector, REPL } = this.props

return (
<span className="repl-input-element flex-fill">
Expand Down Expand Up @@ -69,7 +69,7 @@ export default class FancyPipeline extends React.PureComponent<Props> {
{redirect && (
<React.Fragment>
{this.linebreak()}
{this.pipe('>')}
{this.pipe(redirector)}
<span className="clickable" onClick={() => REPL.pexec(`ls ${redirect}`)}>
{redirect}
</span>
Expand Down

0 comments on commit 76f2f4c

Please sign in to comment.