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

pkgxdev / pkgx / 6373972470

01 Oct 2023 11:10PM UTC coverage: 97.524% (+1.0%) from 96.493%
6373972470

push

github

mxcl
pkgx

359 of 380 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%)

120.74 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)
141✔
71

72
    switch (type) {
141✔
73
    case '+':
141✔
74
      pkgs.plus.push(content)
158✔
75
      break
158✔
76
    case '-':
141✔
77
      pkgs.minus.push(content)
143✔
78
      break
143✔
79
    case '--':
141✔
80
      switch (content) {
189✔
81
      case 'sync':
189✔
82
        flags.sync = true
191✔
83
        break
191✔
84
      case 'update':
189✔
85
        flags.update = true
191✔
86
        break
191✔
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':
189✔
93
      case 'integrate':
189✔
94
      case 'internal.activate':
189✔
95
      case 'help':
189✔
96
      case 'version':
189✔
97
      case 'provider':
189✔
98
      case 'shell-completion':
189✔
99
      case 'internal.use':
189✔
100
        if (mode) throw new UsageError({msg: 'multiple modes specified'})
655✔
101
        mode = content
229✔
102
        break
229✔
103
      case 'silent':
189✔
104
        flags.verbosity = -2
191✔
105
        break
191✔
106
      case 'quiet':
189✔
107
        flags.verbosity = -1
191✔
108
        break
191✔
109
      case 'dry-run':
189✔
110
        dryrun = true
193✔
111
        break
193✔
112
      case '':
189✔
113
        // empty the main loop iterator
191✔
114
        for (const arg of it) args.push(arg)
191✔
115
        break
191✔
116
      default: {
388✔
117
        const match = content.match(/^verbose(=-?\d+)?$/)
199✔
118
        if (match) {
199✔
119
          flags.verbosity = flatmap(match[1], n => parseInt(n.slice(1))!) ?? 1
207✔
120
        } else {
199✔
121
          throw new UsageError(arg)
201✔
122
        }
201✔
123
      }}
388✔
124
      break
227✔
125
    default:
141✔
126
      /// unrecognized args means the start of the runner args
161✔
127
      args.push(arg)
161✔
128
      for (const arg of it) args.push(arg)
161✔
129
    }
161✔
130
  }
161✔
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] {
93✔
168
  switch (arg[0]) {
93✔
169
  case '+': {
205✔
170
    const content = arg.slice(1)
112✔
171
    if (!content) throw new UsageError(arg)
112✔
172
    return ['+', content]
516✔
173
  }
129✔
174
  case '-':
93✔
175
    if (arg[1] == '-') {
145✔
176
      return ['--', arg.slice(2)]
772✔
177
    } else {
145✔
178
      const content = arg.slice(1)
149✔
179
      if (!content) throw new UsageError(arg)
149✔
180
      return ['-', content]
604✔
181
    }
151✔
182
  default:
93✔
183
    return [undefined, arg]
452✔
184
  }
93✔
185
}
93✔
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