hackmud-script-manager 0.20.4-1581594 → 0.20.4-1d688c1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,6 +20,10 @@ You can read about how HSM works [in my blog post](https://samual.uk/blog/js-cod
20
20
  > ```
21
21
  > You will need to run `Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser` in PowerShell as an administrator. For more information, see [Microsoft's page about Execution Policies](https://learn.microsoft.com/en-gb/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4).
22
22
 
23
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/69a371fe-f8c8-43fe-b3c7-39f3735ce6fb)
24
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/08103f9e-74fa-4a56-a739-94858ba8c139)
25
+ ![image](https://github.com/samualtnorman/hackmud-script-manager/assets/18307063/25ccb86d-1fe3-4632-b703-ac47f5b32c9c)
26
+
23
27
  ## Features
24
28
  - Minification
25
29
  - This includes auto quine cheating.
package/bin/hsm.js CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { Cache } from "@samual/lib/Cache"
2
+ import { AutoMap } from "@samual/lib/AutoMap"
3
3
  import { assert } from "@samual/lib/assert"
4
4
  import { countHackmudCharacters } from "@samual/lib/countHackmudCharacters"
5
5
  import { writeFilePersistent } from "@samual/lib/writeFilePersistent"
@@ -13,10 +13,10 @@ import { syncMacros } from "../syncMacros.js"
13
13
  import "@samual/lib/readDirectoryWithStats"
14
14
  import "path/posix"
15
15
  import "@samual/lib/copyFilePersistent"
16
- const version = "0.20.4-1581594",
16
+ const formatOption = name => colourN(`-${1 == name.length ? "" : "-"}${name}`),
17
17
  options = new Map(),
18
18
  commands = [],
19
- userColours = new Cache(user => {
19
+ userColours = new AutoMap(user => {
20
20
  let hash = 0
21
21
  for (const char of user) hash += (hash >> 1) + hash + "xi1_8ratvsw9hlbgm02y5zpdcn7uekof463qj".indexOf(char) + 1
22
22
  return [colourJ, colourK, colourM, colourW, colourL, colourB][hash % 6](user)
@@ -24,16 +24,16 @@ const version = "0.20.4-1581594",
24
24
  log = message => console.log(colourS(message))
25
25
  for (const argument of process.argv.slice(2))
26
26
  if ("-" == argument[0]) {
27
- const [key, valueRaw] = argument.split("=")
28
- let value = valueRaw
29
- if (value)
30
- if ("true" == value) value = !0
31
- else if ("false" == value) value = !1
32
- else {
33
- const number = Number(value)
34
- isFinite(number) && (value = number)
35
- }
36
- else value = !0
27
+ const argumentEqualsIndex = argument.indexOf("=")
28
+ let key, value
29
+ if (-1 == argumentEqualsIndex) {
30
+ key = argument
31
+ value = !0
32
+ } else {
33
+ key = argument.slice(0, argumentEqualsIndex)
34
+ value = argument.slice(argumentEqualsIndex + 1)
35
+ "true" == value ? (value = !0) : "false" == value && (value = !1)
36
+ }
37
37
  if ("-" == argument[1]) options.set(key.slice(2), value)
38
38
  else for (const option of key.slice(1)) options.set(option, value)
39
39
  } else commands.push(argument)
@@ -58,13 +58,14 @@ const pushModule = import("../push.js"),
58
58
  process.version.startsWith("v21.") &&
59
59
  console.warn(
60
60
  colourF(
61
- "Warning: Support for Node.js 21 will be dropped in the next minor version of HSM\n You should update your version of Node.js\n https://nodejs.org/en/download/package-manager"
61
+ `Warning: Support for Node.js 21 will be dropped in the next minor version of HSM\n Your current version of Node.js is ${chalk.bold(process.version)}\n You should update your version of Node.js\n https://nodejs.org/en/download/package-manager\n`
62
62
  )
63
63
  )
64
64
  if ("v" == commands[0] || "version" == commands[0] || popOption("version", "v")?.value) {
65
- console.log(version)
65
+ console.log("0.20.4-1d688c1")
66
66
  process.exit()
67
67
  }
68
+ let warnedDeprecatedEmitDtsAlias = !1
68
69
  if (popOption("help", "h")?.value) {
69
70
  logHelp()
70
71
  process.exit()
@@ -77,13 +78,28 @@ switch (commands[0]) {
77
78
  case "golf":
78
79
  case "minify":
79
80
  {
80
- const noMinifyOption = popOption("no-minify", "skip-minify"),
81
- mangleNamesOption = popOption("mangle-names"),
81
+ const noMinifyOption = popOption("no-minify", "skip-minify")
82
+ noMinifyOption &&
83
+ "no-minify" != noMinifyOption.name &&
84
+ console.warn(
85
+ colourF(
86
+ `Warning: ${formatOption(noMinifyOption.name)} is being deprecated and will be removed in the next minor\n release of HSM\n You should switch to using its alias ${colourN("--no-minify")}\n`
87
+ )
88
+ )
89
+ const mangleNamesOption = popOption("mangle-names"),
82
90
  forceQuineCheatsOption = popOption("force-quine-cheats"),
83
- noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption
91
+ noQuineCheatsOptions = popOption("no-quine-cheats"),
92
+ noMinifyIncompatibleOption = mangleNamesOption || forceQuineCheatsOption || noQuineCheatsOptions
84
93
  if (noMinifyOption && noMinifyIncompatibleOption) {
85
94
  logError(
86
- `Options ${colourN(noMinifyOption.name)} and ${colourN(noMinifyIncompatibleOption.name)} are incompatible\n`
95
+ `Options ${formatOption(noMinifyOption.name)} and ${formatOption(noMinifyIncompatibleOption.name)} are incompatible\n`
96
+ )
97
+ logHelp()
98
+ process.exit(1)
99
+ }
100
+ if (forceQuineCheatsOption && noQuineCheatsOptions) {
101
+ logError(
102
+ `Options ${formatOption(forceQuineCheatsOption.name)} and ${formatOption(noQuineCheatsOptions.name)} are incompatible\n`
87
103
  )
88
104
  logHelp()
89
105
  process.exit(1)
@@ -91,6 +107,7 @@ switch (commands[0]) {
91
107
  noMinifyOption && assertOptionIsBoolean(noMinifyOption)
92
108
  mangleNamesOption && assertOptionIsBoolean(mangleNamesOption)
93
109
  forceQuineCheatsOption && assertOptionIsBoolean(forceQuineCheatsOption)
110
+ noQuineCheatsOptions && assertOptionIsBoolean(noQuineCheatsOptions)
94
111
  if ("golf" == commands[0] || "minify" == commands[0]) {
95
112
  const watchOption = popOption("watch"),
96
113
  target = commands[1]
@@ -106,6 +123,7 @@ switch (commands[0]) {
106
123
  )
107
124
  process.exit(1)
108
125
  }
126
+ complainAboutUnrecognisedOptions()
109
127
  const { processScript } = await processScriptModule,
110
128
  fileBaseName = basename(target, fileExtension),
111
129
  fileBaseNameEndsWithDotSrc = fileBaseName.endsWith(".src"),
@@ -134,7 +152,7 @@ switch (commands[0]) {
134
152
  scriptName,
135
153
  filePath: target,
136
154
  mangleNames: mangleNamesOption?.value,
137
- forceQuineCheats: forceQuineCheatsOption?.value
155
+ forceQuineCheats: forceQuineCheatsOption?.value ?? !noQuineCheatsOptions?.value
138
156
  }),
139
157
  timeTook = performance.now() - timeStart
140
158
  for (const { message, line } of warnings)
@@ -177,7 +195,58 @@ switch (commands[0]) {
177
195
  process.exit(1)
178
196
  }
179
197
  } else scripts.push("*.*")
180
- if ("push" == commands[0]) {
198
+ const watchOption = popOption("watch")
199
+ if ("push" != commands[0] || watchOption?.value) {
200
+ const dtsPathOption = popOption(
201
+ "dts-path",
202
+ "type-declaration-path",
203
+ "type-declaration",
204
+ "dts",
205
+ "gen-types"
206
+ )
207
+ dtsPathOption &&
208
+ "dts-path" != dtsPathOption.name &&
209
+ "type-declaration-path" != dtsPathOption.name &&
210
+ console.warn(
211
+ colourF(
212
+ `Warning: ${formatOption(dtsPathOption.name)} is being deprecated and will be removed in the\n next minor release of HSM\n You should switch to using its alias ${colourN("--dts-path")}\n`
213
+ )
214
+ )
215
+ complainAboutUnrecognisedOptions()
216
+ const { watch } = await watchModule
217
+ watch(sourcePath, hackmudPath, {
218
+ scripts,
219
+ onPush: info => logInfo(info, hackmudPath),
220
+ typeDeclarationPath: dtsPathOption?.value.toString(),
221
+ minify: noMinifyOption && !noMinifyOption.value,
222
+ mangleNames: mangleNamesOption?.value,
223
+ onReady: () => log("Watching"),
224
+ forceQuineCheats: forceQuineCheatsOption?.value ?? !noQuineCheatsOptions?.value
225
+ })
226
+ autoExit = !1
227
+ } else {
228
+ const dtsPathOption = popOption("dts-path")
229
+ complainAboutUnrecognisedOptions()
230
+ let declarationPathPromise
231
+ if (dtsPathOption) {
232
+ if ("string" != typeof dtsPathOption.value) {
233
+ logError(
234
+ `Option ${formatOption(dtsPathOption.name)} must be a string, got ${colourV(dtsPathOption.value)}\n`
235
+ )
236
+ logHelp()
237
+ process.exit(1)
238
+ }
239
+ let typeDeclarationPath = resolve(dtsPathOption.value)
240
+ const typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
241
+ declarationPathPromise = writeFile(typeDeclarationPath, typeDeclaration)
242
+ .catch(error => {
243
+ assert(error instanceof Error, "src/bin/hsm.ts:288:38")
244
+ if ("EISDIR" != error.code) throw error
245
+ typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
246
+ return writeFile(typeDeclarationPath, typeDeclaration)
247
+ })
248
+ .then(() => typeDeclarationPath)
249
+ }
181
250
  const { push, MissingSourceFolderError, MissingHackmudFolderError, NoUsersError } =
182
251
  await pushModule,
183
252
  infos = await push(sourcePath, hackmudPath, {
@@ -185,7 +254,7 @@ switch (commands[0]) {
185
254
  onPush: info => logInfo(info, hackmudPath),
186
255
  minify: noMinifyOption && !noMinifyOption.value,
187
256
  mangleNames: mangleNamesOption?.value,
188
- forceQuineCheats: forceQuineCheatsOption?.value
257
+ forceQuineCheats: forceQuineCheatsOption?.value ?? !noQuineCheatsOptions?.value
189
258
  })
190
259
  if (infos instanceof Error) {
191
260
  logError(infos.message)
@@ -198,24 +267,8 @@ switch (commands[0]) {
198
267
  `If this is not where your hackmud folder is, you can specify it with the\n${colourN("--hackmud-path")}=${colourB("<path>")} option or ${colourN("HSM_HACKMUD_PATH")} environment variable`
199
268
  )
200
269
  } else infos.length || logError("Could not find any scripts to push")
201
- } else {
202
- const typeDeclarationPathOption = popOption(
203
- "type-declaration-path",
204
- "type-declaration",
205
- "dts",
206
- "gen-types"
207
- ),
208
- { watch } = await watchModule
209
- watch(sourcePath, hackmudPath, {
210
- scripts,
211
- onPush: info => logInfo(info, hackmudPath),
212
- typeDeclarationPath: typeDeclarationPathOption?.value.toString(),
213
- minify: noMinifyOption && !noMinifyOption.value,
214
- mangleNames: mangleNamesOption?.value,
215
- onReady: () => log("Watching"),
216
- forceQuineCheats: forceQuineCheatsOption?.value
217
- })
218
- autoExit = !1
270
+ declarationPathPromise &&
271
+ log("Wrote type declaration to " + chalk.bold(await declarationPathPromise))
219
272
  }
220
273
  }
221
274
  }
@@ -229,6 +282,7 @@ switch (commands[0]) {
229
282
  logHelp()
230
283
  process.exit(1)
231
284
  }
285
+ complainAboutUnrecognisedOptions()
232
286
  const sourcePath = commands[2] || "."
233
287
  await pull(sourcePath, hackmudPath, script).catch(error => {
234
288
  console.error(error)
@@ -238,8 +292,9 @@ switch (commands[0]) {
238
292
  break
239
293
  case "sync-macros":
240
294
  {
241
- const hackmudPath = getHackmudPath(),
242
- { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
295
+ const hackmudPath = getHackmudPath()
296
+ complainAboutUnrecognisedOptions()
297
+ const { macrosSynced, usersSynced } = await syncMacros(hackmudPath)
243
298
  log(`Synced ${macrosSynced} macros to ${usersSynced} users`)
244
299
  }
245
300
  break
@@ -247,7 +302,16 @@ switch (commands[0]) {
247
302
  case "gen-type-declaration":
248
303
  case "gen-dts":
249
304
  case "gen-types":
305
+ case "emit-dts":
250
306
  {
307
+ if ("emit-dts" != commands[0] && "gen-dts" != commands[0]) {
308
+ warnedDeprecatedEmitDtsAlias = !0
309
+ console.warn(
310
+ colourF(
311
+ `Warning: ${colourC("hsm")} ${colourL(commands[0])} is being deprecated and will be removed\n in the next minor release of HSM\n You should switch to using its alias ${colourC("hsm")} ${colourL("emit-dts")}\n`
312
+ )
313
+ )
314
+ }
251
315
  const hackmudPath = getHackmudPath(),
252
316
  target = commands[1]
253
317
  if (!target) {
@@ -255,12 +319,13 @@ switch (commands[0]) {
255
319
  logHelp()
256
320
  process.exit(1)
257
321
  }
322
+ complainAboutUnrecognisedOptions()
258
323
  const sourcePath = resolve(target),
259
324
  outputPath = commands[2] || "./player.d.ts",
260
325
  typeDeclaration = await generateTypeDeclaration(sourcePath, hackmudPath)
261
326
  let typeDeclarationPath = resolve(outputPath)
262
327
  await writeFile(typeDeclarationPath, typeDeclaration).catch(error => {
263
- assert(error instanceof Error, "src/bin/hsm.ts:330:35")
328
+ assert(error instanceof Error, "src/bin/hsm.ts:422:35")
264
329
  if ("EISDIR" != error.code) throw error
265
330
  typeDeclarationPath = resolve(typeDeclarationPath, "player.d.ts")
266
331
  return writeFile(typeDeclarationPath, typeDeclaration)
@@ -269,7 +334,6 @@ switch (commands[0]) {
269
334
  }
270
335
  break
271
336
  case "help":
272
- case "h":
273
337
  logHelp()
274
338
  break
275
339
  default:
@@ -279,23 +343,21 @@ switch (commands[0]) {
279
343
  autoExit && process.exit()
280
344
  function logHelp() {
281
345
  const pushCommandDescription = "Push scripts from a directory to hackmud user's scripts directories",
282
- forceQuineCheatsOptionDescription = `Force quine cheats on. Use ${colourN("--force-quine-cheats")}=${colourV("false")} to force off`,
283
346
  hackmudPathOption = `${colourN("--hackmud-path")}=${colourB("<path>")}\n Override hackmud path`
284
- console.log(colourN("Version") + colourS(": ") + colourV(version))
285
347
  switch (commands[0]) {
286
348
  case "dev":
287
349
  case "watch":
288
350
  case "push":
289
351
  console.log(
290
352
  colourS(
291
- `\n${colourJ("push" == commands[0] ? pushCommandDescription : "Watch a directory and push a script when modified")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB('<directory> ["<script user>.<script name>"...]')}\n\n${colourA("Arguments:")}\n${colourB("<directory>")}\n The source directory containing your scripts\n${colourB("<script user>")}\n A user to push script(s) to. Can be set to wild card (${colourV("*")}) which will try\n and discover users to push to\n${colourB("<script name>")}\n Name of a script to push. Can be set to wild card (${colourV("*")}) to find all scripts\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}\n${hackmudPathOption}\n${"push" == commands[0] ? "" : `${colourN("--type-declaration-path")}=${colourB("<path>")}\n Path to generate a type declaration file for the scripts\n`}\n${colourA("Examples:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")}\n Pushes all scripts found in ${colourV("src")} folder to all users\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")}\n Pushes a script named ${colourL("bar")} found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")} ${colourC("baz")}${colourV(".")}${colourL("qux")}\n Multiple can be specified\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("foo")}\n Pushes all scripts named ${colourL("foo")} found in ${colourV("src")} folder to all user\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to all users`
353
+ `${colourJ("push" == commands[0] ? pushCommandDescription : "Watch a directory and push a script when modified")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB('<directory> ["<script user>.<script name>"...]')}\n\n${colourA("Arguments:")}\n${colourB("<directory>")}\n The source directory containing your scripts\n${colourB("<script user>")}\n A user to push script(s) to. Can be set to wild card (${colourV("*")}) which will try\n and discover users to push to\n${colourB("<script name>")}\n Name of a script to push. Can be set to wild card (${colourV("*")}) to find all scripts\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}, ${colourN("--no-quine-cheats")}\n Force quine cheats on or off\n${hackmudPathOption}\n${colourN("--dts-path")}=${colourB("<path>")}\n Path to generate a type declaration (.d.ts) file for the scripts\n${colourN("--watch")}\n Watch for changes\n\n${colourA("Examples:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")}\n Pushes all scripts found in ${colourV("src")} folder to all users\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")}\n Pushes a script named ${colourL("bar")} found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("bar")} ${colourC("baz")}${colourV(".")}${colourL("qux")}\n Multiple can be specified\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("foo")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to user ${userColours.get("foo")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("foo")}\n Pushes all scripts named ${colourL("foo")} found in ${colourV("src")} folder to all user\n${colourC("hsm")} ${colourL(commands[0])} ${colourV("src")} ${colourC("*")}${colourV(".")}${colourL("*")}\n Pushes all scripts found in ${colourV("src")} folder to all users`
292
354
  )
293
355
  )
294
356
  break
295
357
  case "pull":
296
358
  console.log(
297
359
  colourS(
298
- `\n${colourJ("Pull a script a from a hackmud user's script directory")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<script user>")}${colourV(".")}${colourB("<script name>")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
360
+ `${colourJ("Pull a script a from a hackmud user's script directory")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<script user>")}${colourV(".")}${colourB("<script name>")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
299
361
  )
300
362
  )
301
363
  break
@@ -303,7 +365,7 @@ function logHelp() {
303
365
  case "golf":
304
366
  console.log(
305
367
  colourS(
306
- `\n${colourJ("Minify a script file on the spot")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<target> [output path]")}\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}\n ${forceQuineCheatsOptionDescription}\n${colourN("--watch")}\n Watch for changes`
368
+ `${colourJ("Minify a script file on the spot")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<target> [output path]")}\n\n${colourA("Options:")}\n${colourN("--no-minify")}\n Skip minification to produce a "readable" script\n${colourN("--mangle-names")}\n Reduce character count further but lose function names in error call stacks\n${colourN("--force-quine-cheats")}, ${colourN("--no-quine-cheats")}\n Force quine cheats on or off\n${colourN("--watch")}\n Watch for changes`
307
369
  )
308
370
  )
309
371
  break
@@ -311,6 +373,15 @@ function logHelp() {
311
373
  case "gen-type-declaration":
312
374
  case "gen-dts":
313
375
  case "gen-types":
376
+ case "emit-dts":
377
+ warnedDeprecatedEmitDtsAlias ||
378
+ "emit-dts" == commands[0] ||
379
+ "gen-dts" == commands[0] ||
380
+ console.warn(
381
+ colourF(
382
+ `Warning: ${colourC("hsm")} ${colourL(commands[0])} is being deprecated and will be removed\n in the next minor release of HSM\n You should switch to using its alias ${colourC("hsm")} ${colourL("emit-dts")}\n`
383
+ )
384
+ )
314
385
  console.log(
315
386
  colourS(
316
387
  `${colourJ("Generate a type declaration file for a directory of scripts")}\n\n${colourA("Usage:")}\n${colourC("hsm")} ${colourL(commands[0])} ${colourB("<directory> [output path]")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
@@ -320,14 +391,14 @@ function logHelp() {
320
391
  case "sync-macros":
321
392
  console.log(
322
393
  colourS(
323
- `\n${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
394
+ `${colourJ("Sync macros across all hackmud users")}\n\n${colourA("Options:")}\n${hackmudPathOption}`
324
395
  )
325
396
  )
326
397
  break
327
398
  default:
328
399
  console.log(
329
400
  colourS(
330
- `\n${colourJ("Hackmud Script Manager")}\n\n${colourA("Commands:")}\n${colourL("push")}\n ${pushCommandDescription}\n${colourL("dev")}\n Watch a directory and push a script when modified\n${colourL("golf")}\n Minify a script file on the spot\n${colourL("gen-dts")}\n Generate a type declaration file for a directory of scripts\n${colourL("sync-macros")}\n Sync macros across all hackmud users\n${colourL("pull")}\n Pull a script a from a hackmud user's script directory`
401
+ `${colourJ("Hackmud Script Manager")}\n${colourN("Version") + colourS(": ") + colourV("0.20.4-1d688c1")}\n\n${colourA("Commands:")}\n${colourL("push")}\n ${pushCommandDescription}\n${colourL("minify")}\n Minify a script file on the spot\n${colourL("emit-dts")}\n Generate a type declaration file for a directory of scripts\n${colourL("sync-macros")}\n Sync macros across all hackmud users\n${colourL("pull")}\n Pull a script a from a hackmud user's script directory\n\n${colourA("Options:")}\n${colourN("--help")}\n Can be used on any command e.g. ${colourC("hsm")} ${colourL("push")} ${colourN("--help")} to show helpful information`
331
402
  )
332
403
  )
333
404
  }
@@ -346,20 +417,32 @@ function logError(message) {
346
417
  }
347
418
  function getHackmudPath() {
348
419
  const hackmudPathOption = popOption("hackmud-path")
349
- if (null != hackmudPathOption && "string" != typeof hackmudPathOption) {
350
- logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption)}\n`)
351
- logHelp()
352
- process.exit(1)
420
+ if (hackmudPathOption) {
421
+ if ("string" != typeof hackmudPathOption.value) {
422
+ logError(`Option ${colourN("--hackmud-path")} must be a string, got ${colourV(hackmudPathOption.value)}\n`)
423
+ logHelp()
424
+ process.exit(1)
425
+ }
426
+ if (!hackmudPathOption.value) {
427
+ logError(`Option ${colourN("--hackmud-path")} was specified but empty\n`)
428
+ logHelp()
429
+ process.exit(1)
430
+ }
431
+ return hackmudPathOption.value
353
432
  }
354
- return (
355
- hackmudPathOption ||
356
- process.env.HSM_HACKMUD_PATH ||
357
- ("win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud"))
358
- )
433
+ if (null != process.env.HSM_HACKMUD_PATH) {
434
+ if (!process.env.HSM_HACKMUD_PATH) {
435
+ logError(`Environment variable ${colourN("HSM_HACKMUD_PATH")} was specified but empty\n`)
436
+ logHelp()
437
+ process.exit(1)
438
+ }
439
+ return process.env.HSM_HACKMUD_PATH
440
+ }
441
+ return "win32" == process.platform ? resolve(process.env.APPDATA, "hackmud") : resolve(homedir(), ".config/hackmud")
359
442
  }
360
443
  function assertOptionIsBoolean(option) {
361
444
  if ("boolean" != typeof option.value) {
362
- logError(`The value for ${colourN(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
445
+ logError(`The value for ${formatOption(option.name)} must be ${colourV("true")} or ${colourV("false")}\n`)
363
446
  logHelp()
364
447
  process.exit(1)
365
448
  }
@@ -367,16 +450,21 @@ function assertOptionIsBoolean(option) {
367
450
  function popOption(...names) {
368
451
  const presentOptionNames = names.filter(name => options.has(name))
369
452
  if (!presentOptionNames.length) return
370
- const presentOptionNamesWithDashDash = presentOptionNames.map(name =>
371
- colourN(`-${1 == name.length ? "" : "-"}${name}`)
372
- )
373
453
  if (presentOptionNames.length > 1) {
374
454
  logError(
375
- `The options ${presentOptionNamesWithDashDash.join(", ")} are aliases for each other. Please only specify one`
455
+ `The options ${presentOptionNames.map(formatOption).join(", ")} are aliases for each other. Please only specify one`
376
456
  )
377
457
  process.exit(1)
378
458
  }
379
459
  const value = options.get(presentOptionNames[0])
380
460
  options.delete(presentOptionNames[0])
381
- return { name: presentOptionNamesWithDashDash[0], value }
461
+ return { name: presentOptionNames[0], value }
462
+ }
463
+ function complainAboutUnrecognisedOptions() {
464
+ if (options.size) {
465
+ logError(
466
+ `Unrecognised option${options.size > 1 ? "s" : ""}: ${[...options.keys()].map(formatOption).join(", ")}`
467
+ )
468
+ process.exit(1)
469
+ }
382
470
  }