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

Sign up to get free protection for your applications and to get access to all the features.
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
  }