• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

pkgxdev / pkgx / 6372742245

01 Oct 2023 07:01PM UTC coverage: 98.037% (+0.5%) from 97.524%
6372742245

push

github

mxcl
pkgx

353 of 365 branches covered (0.0%)

108 of 117 new or added lines in 19 files covered. (92.31%)

1 existing line in 1 file now uncovered.

1295 of 1316 relevant lines covered (98.4%)

121.28 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.76
/src/parse-args.ts
1
import { UsageError } from "./utils/error.ts"
2✔
2
import { Path, utils } from "pkgx"
2✔
3
const { flatmap } = utils
2✔
4

5
type Pkgs = {
6
  plus: string[]
7
  minus: string[]
8
}
9

10
export type Args = {
11
  flags: Flags
12
} & (
13
  {
14
    mode: 'x' | 'run'
15
    args: string[]
16
    pkgs: Pkgs
17
  } | {
18
    mode: 'internal.use'
19
    pkgs: Pkgs
20
  } | {
21
    mode: 'env'
22
    pkgs: {
23
      plus: string[]
24
      minus: string[]
25
    }
26
  } | {
27
    mode: 'shellcode' | 'version' | 'help'
28
  } | {
29
    mode: 'integrate' | 'deintegrate'
30
    dryrun: boolean
31
  } | {
32
    mode: 'provider' | 'shell-completion'
33
    args: string[]
34
  } | {
35
    mode: 'internal.activate'
36
    dir: Path
37
  } | {
38
    mode: 'install'
39
    args: string[]
40
  }
41
)
42

43
interface Flags {
44
  sync: boolean
45
  update: boolean
46
  verbosity?: number
47
}
48

49
export default function(input: string[]): Args {
2✔
50
  const it = input[Symbol.iterator]()
50✔
51
  const pkgs: Pkgs = { plus: [], minus: [] }
200✔
52
  const args: string[] = []
50✔
53
  const flags: Flags = {
50✔
54
    sync: false,
50✔
55
    update: false
50✔
56
  }
50✔
57
  let mode: string | undefined
50✔
58
  let dryrun: boolean | undefined
50✔
59

60
  switch (input[0]) {
50✔
61
  case 'deintegrate':
50✔
62
  case 'integrate':
50✔
63
  case 'install':
50✔
64
  case 'run':
50✔
65
    mode = input[0]
60✔
66
    it.next()  // consume the subcommand
60✔
67
  }
50✔
68

69
  for (const arg of it) {
50✔
70
    const [type, content] = parse(arg)
149✔
71

72
    switch (type) {
149✔
73
    case '+':
149✔
74
      pkgs.plus.push(content)
174✔
75
      break
174✔
76
    case '-':
149✔
77
      pkgs.minus.push(content)
151✔
78
      break
151✔
79
    case '--':
149✔
80
      switch (content) {
197✔
81
      case 'sync':
197✔
82
        flags.sync = true
199✔
83
        break
199✔
84
      case 'update':
197✔
85
        flags.update = true
199✔
86
        break
199✔
87
      case 'provides':
×
88
        if (mode) throw new UsageError({msg: 'multiple modes specified'})
×
NEW
89
        console.error("%cdeprecated: %cuse pkgx --provider instead", 'color: red', 'color: initial')
×
90
        mode = 'provider'
×
91
        break
×
92
      case 'shellcode':
197✔
93
      case 'integrate':
197✔
94
      case 'internal.activate':
197✔
95
      case 'help':
197✔
96
      case 'version':
197✔
97
      case 'provider':
197✔
98
      case 'shell-completion':
197✔
99
      case 'internal.use':
197✔
100
        if (mode) throw new UsageError({msg: 'multiple modes specified'})
679✔
101
        mode = content
237✔
102
        break
237✔
103
      case 'silent':
197✔
104
        flags.verbosity = -2
199✔
105
        break
199✔
106
      case 'quiet':
197✔
107
        flags.verbosity = -1
199✔
108
        break
199✔
109
      case 'dry-run':
197✔
110
        dryrun = true
201✔
111
        break
201✔
112
      case '':
197✔
113
        // empty the main loop iterator
199✔
114
        for (const arg of it) args.push(arg)
199✔
115
        break
199✔
116
      default: {
404✔
117
        const match = content.match(/^verbose(=-?\d+)?$/)
207✔
118
        if (match) {
207✔
119
          flags.verbosity = flatmap(match[1], n => parseInt(n.slice(1))!) ?? 1
215✔
120
        } else {
207✔
121
          throw new UsageError(arg)
209✔
122
        }
209✔
123
      }}
404✔
124
      break
235✔
125
    default:
149✔
126
      /// unrecognized args means the start of the runner args
169✔
127
      args.push(arg)
169✔
128
      for (const arg of it) args.push(arg)
169✔
129
    }
169✔
130
  }
169✔
131

132
  if (dryrun !== undefined && !(mode == 'integrate' || mode == 'deintegrate')) {
50✔
133
    throw new UsageError({msg: '--dry-run cannot be specified with this mode'})
156✔
134
  }
52✔
135

136
  switch (mode) {
82✔
137
  case undefined:
50✔
138
    if (args.length) {
66✔
139
      return { mode: 'x', flags, pkgs, args }
432✔
140
    } else {
66✔
141
      return { mode: 'env', flags, pkgs }
380✔
142
    }
76✔
143
  case 'internal.use':
50✔
144
    return { mode, flags, pkgs }
260✔
145
  case 'run':
50✔
146
    return { mode, flags, pkgs, args }
312✔
147
  case 'provider':
50✔
148
  case 'shell-completion':
50✔
149
    return { mode, flags, args }
260✔
150
  case 'internal.activate':
50✔
151
    return { mode, flags, dir: new Path(args[0]) }
260✔
152
  case 'install':
50✔
153
    return { mode, flags, args }
260✔
154
  case 'integrate':
50✔
155
  case 'deintegrate':
50✔
156
    dryrun ??= false
56✔
157
    return { mode, dryrun, flags }
280✔
158
  default:
×
NEW
159
    // deno-lint-ignore no-explicit-any
×
160
    return { mode: mode as any, flags }
×
161
  }
50✔
162
}
50✔
163

164

165
//////////////////////// utils
2✔
166

167
function parse(arg: string): ['+', string] | ['--', string] | ['-', string] | [undefined, string] {
101✔
168
  switch (arg[0]) {
101✔
169
  case '+': {
229✔
170
    const content = arg.slice(1)
128✔
171
    if (!content) throw new UsageError(arg)
128✔
172
    return ['+', content]
612✔
173
  }
153✔
174
  case '-':
101✔
175
    if (arg[1] == '-') {
153✔
176
      return ['--', arg.slice(2)]
804✔
177
    } else {
153✔
178
      const content = arg.slice(1)
157✔
179
      if (!content) throw new UsageError(arg)
157✔
180
      return ['-', content]
636✔
181
    }
159✔
182
  default:
101✔
183
    return [undefined, arg]
484✔
184
  }
101✔
185
}
101✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc