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

pkgxdev / pkgx / 6373966806

01 Oct 2023 11:10PM UTC coverage: 96.493% (-1.5%) from 98.037%
6373966806

push

github

mxcl
pkgx

319 of 338 branches covered (0.0%)

107 of 117 new or added lines in 19 files covered. (91.45%)

17 existing lines in 3 files now uncovered.

1277 of 1316 relevant lines covered (97.04%)

60.86 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"
1✔
2
import { Path, utils } from "pkgx"
1✔
3
const { flatmap } = utils
1✔
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 {
1✔
50
  const it = input[Symbol.iterator]()
25✔
51
  const pkgs: Pkgs = { plus: [], minus: [] }
100✔
52
  const args: string[] = []
25✔
53
  const flags: Flags = {
25✔
54
    sync: false,
25✔
55
    update: false
25✔
56
  }
25✔
57
  let mode: string | undefined
25✔
58
  let dryrun: boolean | undefined
25✔
59

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

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

72
    switch (type) {
75✔
73
    case '+':
75✔
74
      pkgs.plus.push(content)
88✔
75
      break
88✔
76
    case '-':
75✔
77
      pkgs.minus.push(content)
76✔
78
      break
76✔
79
    case '--':
75✔
80
      switch (content) {
99✔
81
      case 'sync':
99✔
82
        flags.sync = true
100✔
83
        break
100✔
84
      case 'update':
99✔
85
        flags.update = true
100✔
86
        break
100✔
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':
99✔
93
      case 'integrate':
99✔
94
      case 'internal.activate':
99✔
95
      case 'help':
99✔
96
      case 'version':
99✔
97
      case 'provider':
99✔
98
      case 'shell-completion':
99✔
99
      case 'internal.use':
99✔
100
        if (mode) throw new UsageError({msg: 'multiple modes specified'})
341✔
101
        mode = content
119✔
102
        break
119✔
103
      case 'silent':
99✔
104
        flags.verbosity = -2
100✔
105
        break
100✔
106
      case 'quiet':
99✔
107
        flags.verbosity = -1
100✔
108
        break
100✔
109
      case 'dry-run':
99✔
110
        dryrun = true
101✔
111
        break
101✔
112
      case '':
99✔
113
        // empty the main loop iterator
100✔
114
        for (const arg of it) args.push(arg)
100✔
115
        break
100✔
116
      default: {
203✔
117
        const match = content.match(/^verbose(=-?\d+)?$/)
104✔
118
        if (match) {
104✔
119
          flags.verbosity = flatmap(match[1], n => parseInt(n.slice(1))!) ?? 1
108✔
120
        } else {
104✔
121
          throw new UsageError(arg)
105✔
122
        }
105✔
123
      }}
203✔
124
      break
118✔
125
    default:
75✔
126
      /// unrecognized args means the start of the runner args
85✔
127
      args.push(arg)
85✔
128
      for (const arg of it) args.push(arg)
85✔
129
    }
85✔
130
  }
85✔
131

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

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

164

165
//////////////////////// utils
1✔
166

167
function parse(arg: string): ['+', string] | ['--', string] | ['-', string] | [undefined, string] {
51✔
168
  switch (arg[0]) {
51✔
169
  case '+': {
116✔
170
    const content = arg.slice(1)
65✔
171
    if (!content) throw new UsageError(arg)
65✔
172
    return ['+', content]
312✔
173
  }
78✔
174
  case '-':
51✔
175
    if (arg[1] == '-') {
77✔
176
      return ['--', arg.slice(2)]
404✔
177
    } else {
77✔
178
      const content = arg.slice(1)
79✔
179
      if (!content) throw new UsageError(arg)
79✔
180
      return ['-', content]
320✔
181
    }
80✔
182
  default:
51✔
183
    return [undefined, arg]
244✔
184
  }
51✔
185
}
51✔
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