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

pkgxdev / pkgx / 6374100438

01 Oct 2023 11:32PM UTC coverage: 98.037% (+0.5%) from 97.524%
6374100438

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.11 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)
145✔
71

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